|
12 | 12 |
|
13 | 13 | namespace rfl { |
14 | 14 |
|
| 15 | +/// Wraps a field value to mark it as an XML attribute. |
| 16 | +/// In XML serialization, fields wrapped in Attribute will be rendered as attributes |
| 17 | +/// on the XML element rather than child elements. For non-XML formats, this wrapper |
| 18 | +/// is transparent and behaves like a normal field. |
| 19 | +/// Example: <element attr="value"> instead of <element><field>value</field></element> |
| 20 | +/// @tparam T The type of the attribute value |
15 | 21 | template <class T> |
16 | 22 | struct Attribute { |
17 | 23 | using Type = T; |
18 | 24 | using ReflectionType = T; |
19 | 25 |
|
| 26 | + /// Default constructor. |
20 | 27 | Attribute() : value_(Type()) {} |
21 | 28 |
|
| 29 | + /// Constructs from a const reference to the value. |
| 30 | + /// @param _value The value to store |
22 | 31 | Attribute(const Type& _value) : value_(_value) {} |
23 | 32 |
|
| 33 | + /// Constructs from an rvalue reference to the value. |
| 34 | + /// @param _value The value to store (will be moved) |
24 | 35 | Attribute(Type&& _value) noexcept : value_(std::move(_value)) {} |
25 | 36 |
|
| 37 | + /// Move constructor. |
| 38 | + /// @param _attr The Attribute to move from |
26 | 39 | Attribute(Attribute<T>&& _attr) noexcept = default; |
27 | 40 |
|
| 41 | + /// Copy constructor. |
| 42 | + /// @param _attr The Attribute to copy from |
28 | 43 | Attribute(const Attribute<Type>& _attr) = default; |
29 | 44 |
|
| 45 | + /// Copy constructor from Attribute with compatible type. |
| 46 | + /// @tparam U Type compatible with T |
| 47 | + /// @param _attr The Attribute to copy the value from |
30 | 48 | template <class U> |
31 | 49 | Attribute(const Attribute<U>& _attr) : value_(_attr.get()) {} |
32 | 50 |
|
| 51 | + /// Move constructor from Attribute with compatible type. |
| 52 | + /// @tparam U Type compatible with T |
| 53 | + /// @param _attr The Attribute to move the value from |
33 | 54 | template <class U> |
34 | 55 | Attribute(Attribute<U>&& _attr) : value_(_attr.get()) {} |
35 | 56 |
|
| 57 | + /// Constructs from any type convertible to Type (copy). |
| 58 | + /// @tparam U Type convertible to T |
| 59 | + /// @param _value The value to convert and store |
36 | 60 | template <class U> |
37 | 61 | requires std::is_convertible_v<U, Type> |
38 | 62 | Attribute(const U& _value) : value_(_value) {} |
39 | 63 |
|
| 64 | + /// Constructs from any type convertible to Type (move). |
| 65 | + /// @tparam U Type convertible to T |
| 66 | + /// @param _value The value to convert and store (will be moved) |
40 | 67 | template <class U> |
41 | 68 | requires std::is_convertible_v<U, Type> |
42 | 69 | Attribute(U&& _value) noexcept : value_(std::forward<U>(_value)) {} |
43 | 70 |
|
| 71 | + /// Constructs from an Attribute with compatible type. |
| 72 | + /// @tparam U Type convertible to T |
| 73 | + /// @param _attr The Attribute to copy the value from |
44 | 74 | template <class U> |
45 | 75 | requires std::is_convertible_v<U, Type> |
46 | 76 | Attribute(const Attribute<U>& _attr) : value_(_attr.value()) {} |
47 | 77 |
|
48 | | - /// Assigns the underlying object to its default value. |
| 78 | + /// Assigns the underlying object to its default value using the Default sentinel. |
| 79 | + /// @tparam U The type (must be default constructible) |
| 80 | + /// @param The default sentinel value |
49 | 81 | template <class U = Type> |
50 | 82 | requires std::is_default_constructible_v<U> |
51 | 83 | Attribute(const Default&) : value_(Type()) {} |
52 | 84 |
|
| 85 | + /// Destructor. |
53 | 86 | ~Attribute() = default; |
54 | 87 |
|
55 | | - /// Returns the underlying object. |
| 88 | + /// Returns the underlying value. |
| 89 | + /// @return Const reference to the stored value |
56 | 90 | const Type& get() const noexcept { return value_; } |
57 | 91 |
|
58 | | - /// Returns the underlying object. |
| 92 | + /// Returns the underlying value. |
| 93 | + /// @return Reference to the stored value |
59 | 94 | Type& get() noexcept { return value_; } |
60 | 95 |
|
61 | | - /// Returns the underlying object. |
| 96 | + /// Dereference operator - returns the underlying value. |
| 97 | + /// @return Reference to the stored value |
62 | 98 | Type& operator*() noexcept { return value_; } |
63 | 99 |
|
64 | | - /// Returns the underlying object. |
| 100 | + /// Dereference operator (const) - returns the underlying value. |
| 101 | + /// @return Const reference to the stored value |
65 | 102 | const Type& operator*() const noexcept { return value_; } |
66 | 103 |
|
67 | | - /// Returns the underlying object. |
| 104 | + /// Function call operator - returns the underlying value. |
| 105 | + /// @return Reference to the stored value |
68 | 106 | Type& operator()() noexcept { return value_; } |
69 | 107 |
|
70 | | - /// Returns the underlying object. |
| 108 | + /// Function call operator (const) - returns the underlying value. |
| 109 | + /// @return Const reference to the stored value |
71 | 110 | const Type& operator()() const noexcept { return value_; } |
72 | 111 |
|
73 | | - /// Assigns the underlying object. |
| 112 | + /// Assigns a new value. |
| 113 | + /// @param _value The value to assign |
| 114 | + /// @return Reference to this Attribute |
74 | 115 | auto& operator=(const Type& _value) { |
75 | 116 | value_ = _value; |
76 | 117 | return *this; |
77 | 118 | } |
78 | 119 |
|
79 | | - /// Assigns the underlying object. |
| 120 | + /// Assigns a new value (move version). |
| 121 | + /// @param _value The value to assign (will be moved) |
| 122 | + /// @return Reference to this Attribute |
80 | 123 | auto& operator=(Type&& _value) noexcept { |
81 | 124 | value_ = std::move(_value); |
82 | 125 | return *this; |
83 | 126 | } |
84 | 127 |
|
85 | | - /// Assigns the underlying object. |
| 128 | + /// Assigns from any type convertible to the underlying type. |
| 129 | + /// @tparam U Type convertible to T |
| 130 | + /// @param _value The value to convert and assign |
| 131 | + /// @return Reference to this Attribute |
86 | 132 | template <class U> |
87 | 133 | requires std::is_convertible_v<U, Type> |
88 | 134 | auto& operator=(const U& _value) { |
89 | 135 | value_ = _value; |
90 | 136 | return *this; |
91 | 137 | } |
92 | 138 |
|
93 | | - /// Assigns the underlying object to its default value. |
| 139 | + /// Assigns the value to its default using the Default sentinel. |
| 140 | + /// @tparam U The type (must be default constructible) |
| 141 | + /// @param The default sentinel value |
| 142 | + /// @return Reference to this Attribute |
94 | 143 | template <class U = Type> |
95 | 144 | requires std::is_default_constructible_v<U> |
96 | 145 | auto& operator=(const Default&) { |
97 | 146 | value_ = Type(); |
98 | 147 | return *this; |
99 | 148 | } |
100 | 149 |
|
101 | | - /// Assigns the underlying object. |
| 150 | + /// Copy assignment operator. |
| 151 | + /// @param _attr The Attribute to copy from |
| 152 | + /// @return Reference to this Attribute |
102 | 153 | Attribute<T>& operator=(const Attribute<T>& _attr) = default; |
103 | 154 |
|
104 | | - /// Assigns the underlying object. |
| 155 | + /// Move assignment operator. |
| 156 | + /// @param _attr The Attribute to move from |
| 157 | + /// @return Reference to this Attribute |
105 | 158 | Attribute<T>& operator=(Attribute<T>&& _attr) = default; |
106 | 159 |
|
107 | | - /// Assigns the underlying object. |
| 160 | + /// Assigns from another Attribute with compatible type (copy). |
| 161 | + /// @tparam U Type compatible with T |
| 162 | + /// @param _attr The Attribute to copy the value from |
| 163 | + /// @return Reference to this Attribute |
108 | 164 | template <class U> |
109 | 165 | auto& operator=(const Attribute<U>& _attr) { |
110 | 166 | value_ = _attr.get(); |
111 | 167 | return *this; |
112 | 168 | } |
113 | 169 |
|
114 | | - /// Assigns the underlying object. |
| 170 | + /// Assigns from another Attribute with compatible type (move). |
| 171 | + /// @tparam U Type compatible with T |
| 172 | + /// @param _attr The Attribute to move the value from |
| 173 | + /// @return Reference to this Attribute |
115 | 174 | template <class U> |
116 | 175 | auto& operator=(Attribute<U>&& _attr) { |
117 | | - value_ = std::forward<T>(_attr.value_); |
| 176 | + value_ = std::move(_attr.value_); |
118 | 177 | return *this; |
119 | 178 | } |
120 | 179 |
|
121 | | - /// We want all parsers other than the XML parser to treat attributes like |
122 | | - /// normal fields, so we just implement the reflection interface. |
| 180 | + /// Returns the underlying value for reflection (used by parsers). |
| 181 | + /// Non-XML parsers treat attributes like normal fields. |
| 182 | + /// @return Const reference to the stored value |
123 | 183 | const ReflectionType& reflection() const { return value_; } |
124 | 184 |
|
125 | | - /// Assigns the underlying object. |
| 185 | + /// Sets the value (copy version). |
| 186 | + /// @param _value The value to set |
126 | 187 | void set(const Type& _value) { value_ = _value; } |
127 | 188 |
|
128 | | - /// Assigns the underlying object. |
| 189 | + /// Sets the value (move version). |
| 190 | + /// @param _value The value to set (will be moved) |
129 | 191 | void set(Type&& _value) { value_ = std::move(_value); } |
130 | 192 |
|
131 | | - /// Returns the underlying object. |
| 193 | + /// Returns the underlying value. |
| 194 | + /// @return Reference to the stored value |
132 | 195 | Type& value() noexcept { return value_; } |
133 | 196 |
|
134 | | - /// Returns the underlying object. |
| 197 | + /// Returns the underlying value (const). |
| 198 | + /// @return Const reference to the stored value |
135 | 199 | const Type& value() const noexcept { return value_; } |
136 | 200 |
|
137 | 201 | /// The underlying value. |
|
0 commit comments