summaryrefslogtreecommitdiff
path: root/src/bindings
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2015-02-12 23:22:50 -0200
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-04-14 01:06:57 -0300
commit5619c6bc8dff95865ddc412d0d5f161dc33f7fcf (patch)
treef63d65a43ae1252a5dc2f91074968619fbd0fe8f /src/bindings
parent5043dcb830e96aa11b04e3bebc935c1c4cc606f2 (diff)
eina_cxx: Fix compatibility between eina::optionals of convertible types
Now an eina::optional that wraps a specific type can be constructed or have content assigned to it using another eina::optional that wraps a different type, provided that the two wrapped types are convertible between each other. Added "disengage" member function to be able to disengage a R-value eina::optional of different contained type. It also adds for increased convenience. Fix constructing an engaged eina::optional from an disengaged one. Fix small assertion problem of trying to construct an eina::optional already flagged as engaged. Fix incorrect use of std::move. Changed it to std::forward. Added constexpr property for trivial constructors. Added auxiliary function "make_optional". Added unit test to check compatibility between eina::optionals of convertible types.
Diffstat (limited to 'src/bindings')
-rw-r--r--src/bindings/eina_cxx/eina_optional.hh100
1 files changed, 93 insertions, 7 deletions
diff --git a/src/bindings/eina_cxx/eina_optional.hh b/src/bindings/eina_cxx/eina_optional.hh
index 64e42d7d8d..7cb2075e0a 100644
--- a/src/bindings/eina_cxx/eina_optional.hh
+++ b/src/bindings/eina_cxx/eina_optional.hh
@@ -66,15 +66,15 @@ struct optional
66 * @brief Create a disengaged object. 66 * @brief Create a disengaged object.
67 * 67 *
68 * This constructor creates a disengaged <tt>eina::optional</tt> 68 * This constructor creates a disengaged <tt>eina::optional</tt>
69 * object, since null pointer is meant to be a valid object type. 69 * object.
70 */ 70 */
71 optional(std::nullptr_t) : engaged(false) 71 constexpr optional(std::nullptr_t) : engaged(false)
72 {} 72 {}
73 73
74 /** 74 /**
75 * @brief Default constructor. Create a disengaged object. 75 * @brief Default constructor. Create a disengaged object.
76 */ 76 */
77 optional() : engaged(false) 77 constexpr optional() : engaged(false)
78 {} 78 {}
79 79
80 /** 80 /**
@@ -158,11 +158,44 @@ struct optional
158 optional(optional<T>&& other) 158 optional(optional<T>&& other)
159 : engaged(false) 159 : engaged(false)
160 { 160 {
161 _construct(std::move(*other)); 161 if(other.engaged) _construct(std::move(*other));
162 other._destroy(); 162 other._destroy();
163 } 163 }
164 164
165 /** 165 /**
166 * @brief Move constructor. Create an object containing the same value as @p other and in the same state.
167 * @param other R-value reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
168 *
169 * This constructor creates an <tt>eina::optional</tt> object with
170 * the same engagement state of @p other. If @p other is engaged then
171 * the contained value of the newly created object is initialized by
172 * moving the contained value of @p other.
173 */
174 template <typename U>
175 optional(optional<U>&& other, typename std::enable_if<std::is_convertible<U, T>::value>::type* = 0)
176 : engaged(false)
177 {
178 if (other.is_engaged()) _construct(std::move(*other));
179 other.disengage();
180 }
181
182 /**
183 * @brief Copy constructor. Create an object containing the same value as @p other and in the same state.
184 * @param other Constant reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
185 *
186 * This constructor creates an <tt>eina::optional</tt> object with
187 * the same engagement state of @p other. If @p other is engaged then
188 * the contained value of the newly created object is initialized by
189 * converting and copying the contained value of @p other.
190 */
191 template <typename U>
192 optional(optional<U> const& other, typename std::enable_if<std::is_convertible<U, T>::value>::type* = 0)
193 : engaged(false)
194 {
195 if (other.is_engaged()) _construct(*other);
196 }
197
198 /**
166 * @brief Assign new content to the object. 199 * @brief Assign new content to the object.
167 * @param other R-value reference to another <tt>eina::optional</tt> object that holds the same value type. 200 * @param other R-value reference to another <tt>eina::optional</tt> object that holds the same value type.
168 * 201 *
@@ -175,8 +208,7 @@ struct optional
175 _self_type& operator=(optional<T>&& other) 208 _self_type& operator=(optional<T>&& other)
176 { 209 {
177 _destroy(); 210 _destroy();
178 engaged = other.engaged; 211 if (other.engaged)
179 if(engaged)
180 _construct(std::move(*other)); 212 _construct(std::move(*other));
181 other._destroy(); 213 other._destroy();
182 return *this; 214 return *this;
@@ -200,6 +232,53 @@ struct optional
200 } 232 }
201 233
202 /** 234 /**
235 * @brief Assign new content to the object.
236 * @param other R-value reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
237 *
238 * This operator replaces the current content of the object. If
239 * @p other is engaged its contained value is moved to this object,
240 * making <tt>*this</tt> be considered engaged too. If @p other is
241 * disengaged <tt>*this</tt> is also made disengaged and its
242 * contained value, if any, is simple destroyed.
243 */
244 template <typename U>
245 typename std::enable_if<std::is_convertible<U, T>::value, _self_type>::type& operator=(optional<U>&& other)
246 {
247 _destroy();
248 if (other.is_engaged())
249 _construct(std::move(*other));
250 other.disengage();
251 return *this;
252 }
253
254 /**
255 * @brief Assign new content to the object.
256 * @param other Constant reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
257 *
258 * This operator replaces the current content of the object. If
259 * @p other is engaged its contained value is converted and copied to this
260 * object, making <tt>*this</tt> be considered engaged too. If @p other is
261 * disengaged <tt>*this</tt> is also made disengaged and its
262 * contained value, if any, is simple destroyed.
263 */
264 template <typename U>
265 typename std::enable_if<std::is_convertible<U, T>::value, _self_type>::type& operator=(optional<U>const& other)
266 {
267 _destroy();
268 if (other.is_engaged())
269 _construct(*other);
270 return *this;
271 }
272
273 /**
274 * @brief Disengage the object, destroying the current contained value, if any.
275 */
276 void disengage()
277 {
278 _destroy();
279 }
280
281 /**
203 * @brief Releases the contained value if the object is engaged. 282 * @brief Releases the contained value if the object is engaged.
204 */ 283 */
205 ~optional() 284 ~optional()
@@ -308,7 +387,7 @@ private:
308 void _construct(U&& object) 387 void _construct(U&& object)
309 { 388 {
310 assert(!is_engaged()); 389 assert(!is_engaged());
311 new (&buffer) T(std::move(object)); 390 new (&buffer) T(std::forward<U>(object));
312 engaged = true; 391 engaged = true;
313 } 392 }
314 393
@@ -338,6 +417,13 @@ private:
338 bool engaged; 417 bool engaged;
339}; 418};
340 419
420template <typename T>
421constexpr optional<typename std::decay<T>::type>
422make_optional(T&& value)
423{
424 return optional<typename std::decay<T>::type>(std::forward<T>(value));
425}
426
341/** 427/**
342 * @brief Swap content with another <tt>eina::optional</tt> object. 428 * @brief Swap content with another <tt>eina::optional</tt> object.
343 * 429 *