DALi Version 1.9.35
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / tizen-wayland / atspi / accessibility-optional.h
1 #ifndef DALI_INTERNAL_ATSPI_ACCESSIBILITY_OPTIONAL_H
2 #define DALI_INTERNAL_ATSPI_ACCESSIBILITY_OPTIONAL_H
3
4 /*
5  * Copyright 2019  Samsung Electronics Co., Ltd
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <cassert>
22 #include <new>
23 #include <type_traits>
24 #include <utility>
25
26 /**
27  * Minimalistic implementation of standard library std::optional (c++17) for c++11 compiler.
28  *
29  * After project conversion to C++17 standard, this template class will be deleted and
30  * Optional will point to std::optional.
31  *
32  * Allowed operations (note, to make code simplier, than original, value class must have accessible copy and move constructor):
33  *  - constructing empty (valueless) object
34  *  - copying Optional (with and without value)
35  *  - moving Optional (with and without value)
36  *  - querying, if Optional has value (via explicit operator bool), for example:
37  *        Optional<int> v = ...;
38  *        if (v) ... // if v has value, then do something
39  *  - accessing value (via operator *), for example:
40  *        Optional<int> v = ...;
41  *        auto z = *v; // z now has the same int, as v (copied)
42  *        auto &y = *v; // y now has REFERENCE to int inside v, so modifying y modifies v
43  */
44
45 template < typename A >
46 class Optional
47 {
48   union
49   {
50     A place;
51   };
52   bool hasValue = false;
53
54 public:
55   /**
56    * @brief Empty constructor.
57    * Creates empty Optional object, which will be false in boolean context.
58    * So:
59    *   \code{.cpp}
60    *   Optional<int> o;
61    *   if (o) printf("1\n");
62    *   \endcode
63    * won't print 1.
64    */
65   Optional() {}
66
67   /**
68    * @brief Single element constructor, when implicit convertion can be applied.
69    * This constructor will be selected, when type of given argument (U) is
70    * implicitly convertable to expected type A. In other words following
71    * code must be valid:
72    *   \code{.cpp}
73    *   A foo() {
74    *     return U();
75    *   }
76    *   \endcode
77    * @param a value held by Optional object will be initialized from a.
78    */
79   template < typename U = A, typename std::enable_if<
80                                  std::is_convertible< U&&, A >::value &&
81                                  std::is_constructible< A, U&& >::value &&
82                                  !std::is_same< typename std::decay< U >::type, Optional< A > >::value,
83                                  int* >::type = nullptr >
84   constexpr Optional( U&& a )
85   : place( std::forward< U >( a ) ),
86     hasValue( true )
87   {
88   }
89
90   /**
91    * @brief Single element constructor, when only explicit convertion can be applied.
92    * This constructor will be selected, when type of given argument (U) is
93    * convertable to expected type A.
94    * @param a value held by Optional object will be initialized from a.
95    */
96   template < typename U = A, typename std::enable_if<
97                                  !std::is_convertible< U&&, A >::value &&
98                                  std::is_constructible< A, U&& >::value &&
99                                  !std::is_same< typename std::decay< U >::type, Optional< A > >::value,
100                                  int* >::type = nullptr >
101   explicit constexpr Optional( U&& a )
102   : place( std::forward< U >( a ) ),
103     hasValue( true )
104   {
105   }
106
107   /**
108    * @brief Copy constructor.
109    * @param v Optional value to copy from. Will cause to copy data held by object v,
110    * if v has data.
111    */
112   Optional( const Optional& v ) : hasValue( v.hasValue )
113   {
114     if( hasValue )
115     {
116       new( &place ) A( v.place );
117     }
118   }
119
120   /**
121    * @brief Move constructor.
122    * @param v Optional value to copy from. Will move data help by v, if any.
123    * After construction \code{.cpp} bool(v) \endcode will be false.
124    */
125   Optional( Optional&& v ) : hasValue( v.hasValue )
126   {
127     if( hasValue )
128     {
129       new( &place ) A( std::move( v.place ) );
130     }
131   }
132
133   /**
134    * @brief Destructor.
135    */
136   ~Optional()
137   {
138     if( hasValue )
139     {
140       place.~A();
141     }
142   }
143
144   /**
145    * @brief Explicit bool operator
146    * Will return true if and only if object is helding data.
147    */
148   explicit operator bool() const
149   {
150     return hasValue;
151   }
152
153   /**
154    * @brief Accessor (*) operator
155    * Will return modifiable reference to held object. Will assert, if not object is held.
156    */
157   A& operator*()
158   {
159     assert( hasValue );
160     return place;
161   }
162
163   /**
164    * @brief Accessor (*) const operator
165    * Will return const reference to held object. Will assert, if not object is held.
166    */
167   const A& operator*() const
168   {
169     assert( hasValue );
170     return place;
171   }
172
173   /**
174    * @brief Accessor (->) operator
175    * Will return pointer to held object allowing access to the value's members.
176    * Will assert, if not object is held.
177    */
178   A* operator->()
179   {
180     assert( hasValue );
181     return &place;
182   }
183
184   /**
185    * @brief Accessor (->) operator
186    * Will return pointer to (const) held object allowing access to the value's members.
187    * Will assert, if not object is held.
188    */
189   const A* operator->() const
190   {
191     assert( hasValue );
192     return &place;
193   }
194
195   /**
196    * @brief Assignment operator
197    * Will copy held value from v, if any.
198    * @param v Value to copy from
199    */
200   Optional& operator=( const Optional& v )
201   {
202     if( this != &v )
203     {
204       if( hasValue != v.hasValue )
205       {
206         if( v.hasValue )
207         {
208           new( &place ) A( v.place );
209         }
210         else
211         {
212           place.~A();
213         }
214         hasValue = v.hasValue;
215       }
216       else if( hasValue )
217       {
218         place = v.place;
219       }
220     }
221     return *this;
222   }
223
224   /**
225    * @brief Assignment move operator
226    * Will move held value from v, if any. In all cases v won't held a value
227    * after assignment is done.
228    * @param v Value to copy from
229    */
230   Optional& operator=( Optional&& v )
231   {
232     if( this != &v )
233     {
234       if( hasValue != v.hasValue )
235       {
236         if( v.hasValue )
237         {
238           new( &place ) A( std::move( v.place ) );
239         }
240         else
241         {
242           place.~A();
243         }
244         hasValue = v.hasValue;
245       }
246       else if( hasValue )
247       {
248         place = std::move( v.place );
249       }
250     }
251     return *this;
252   }
253
254   /**
255    * @brief Assignment operator from value of type held.
256    * Will initialize held value from given parameter a.
257    * Type of the parameter must be the same (barring cv convertions),
258    * as the type of the value held.
259    * @param a Value to copy from
260    */
261   template < class U, class = typename std::enable_if<
262                           std::is_same< typename std::remove_reference< U >::type, A >::value &&
263                           std::is_constructible< A, U >::value &&
264                           std::is_assignable< A&, U >::value >::type >
265   Optional& operator=( U&& a )
266   {
267     if( hasValue )
268     {
269       place = std::forward< U >( a );
270     }
271     else
272     {
273       hasValue = true;
274       new( &place ) A( std::forward< U >( a ) );
275     }
276     return *this;
277   }
278 };
279
280 #endif // DALI_INTERNAL_ATSPI_ACCESSIBILITY_OPTIONAL_H