2 * Copyright 2017 Samsung Electronics Co., Ltd
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 * Minimalistic implementation of standard library std::optional (c++17) for c++11 compiler.
23 * After project conversion to C++17 standard, this template class will be deleted and
24 * Optional will point to std::optional.
26 * Allowed operations (note, to make code simplier, than original, value class must have accessible copy and move constructor):
27 * - constructing empty (valueless) object
28 * - copying Optional (with and without value)
29 * - moving Optional (with and without value)
30 * - querying, if Optional has value (via explicit operator bool), for example:
31 * Optional<int> v = ...;
32 * if (v) ... // if v has value, then do something
33 * - accessing value (via operator *), for example:
34 * Optional<int> v = ...;
35 * auto z = *v; // z now has the same int, as v (copied)
36 * auto &y = *v; // y now has REFERENCE to int inside v, so modifying y modifies v
41 #include <type_traits>
44 template < typename A >
52 bool hasValue = false;
56 * @brief Empty constructor.
57 * Creates empty Optional object, which will be false in boolean context.
61 * if (o) printf("1\n");
68 * @brief Single element constructor, when implicit convertion can be applied.
70 * This constructor will be selected, when type of given argument (U) is
71 * implicitly convertable to expected type A. In other words following
79 * @param a value held by Optional object will be initialized from a.
81 template < typename U = A, typename std::enable_if<
82 std::is_convertible< U&&, A >::value &&
83 std::is_constructible< A, U&& >::value &&
84 !std::is_same< typename std::decay< U >::type, Optional< A > >::value,
85 int* >::type = nullptr >
86 constexpr Optional( U&& a )
87 : place( std::forward< U >( a ) ), hasValue( true )
92 * @brief Single element constructor, when only explicit convertion can be applied.
94 * This constructor will be selected, when type of given argument (U) is
95 * convertable to expected type A.
97 * @param a value held by Optional object will be initialized from a.
99 template < typename U = A, typename std::enable_if<
100 !std::is_convertible< U&&, A >::value &&
101 std::is_constructible< A, U&& >::value &&
102 !std::is_same< typename std::decay< U >::type, Optional< A > >::value,
103 int* >::type = nullptr >
104 explicit constexpr Optional( U&& a )
105 : place( std::forward< U >( a ) ), hasValue( true )
110 * @brief Copy constructor.
112 * @param v Optional value to copy from. Will cause to copy data held by object v,
115 Optional( const Optional& v ) : hasValue( v.hasValue )
118 new( &place ) A( v.place );
122 * @brief Move constructor.
124 * @param v Optional value to copy from. Will move data help by v, if any.
125 * After construction \code{.cpp} bool(v) \endcode will be false.
127 Optional( Optional&& v ) : hasValue( v.hasValue )
130 new( &place ) A( std::move( v.place ) );
145 * @brief Explicit bool operator
147 * Will return true if and only if object is helding data.
149 explicit operator bool() const
155 * @brief Accessor (*) operator
157 * Will return modifiable reference to held object. Will assert, if not object is held.
166 * @brief Accessor (*) const operator
168 * Will return const reference to held object. Will assert, if not object is held.
170 const A& operator*() const
177 * @brief Accessor (->) operator
179 * Will return pointer to held object allowing access to the value's members.
180 * Will assert, if not object is held.
189 * @brief Accessor (->) operator
191 * Will return pointer to (const) held object allowing access to the value's members.
192 * Will assert, if not object is held.
194 const A* operator->() const
201 * @brief Assignment operator
203 * Will copy held value from v, if any.
205 * @param v Value to copy from
207 Optional& operator=( const Optional& v )
211 if( hasValue != v.hasValue )
214 new( &place ) A( v.place );
217 hasValue = v.hasValue;
228 * @brief Assignment move operator
230 * Will move held value from v, if any. In all cases v won't held a value
231 * after assignment is done.
233 * @param v Value to copy from
235 Optional& operator=( Optional&& v )
239 if( hasValue != v.hasValue )
242 new( &place ) A( std::move( v.place ) );
245 hasValue = v.hasValue;
249 place = std::move( v.place );
256 * @brief Assignment operator from value of type held.
258 * Will initialize held value from given parameter a.
259 * Type of the parameter must be the same (barring cv convertions),
260 * as the type of the value held.
262 * @param a Value to copy from
264 template < class U, class = typename std::enable_if<
265 std::is_same< typename std::remove_reference< U >::type, A >::value &&
266 std::is_constructible< A, U >::value &&
267 std::is_assignable< A&, U >::value >::type >
268 Optional& operator=( U&& a )
271 place = std::forward< U >( a );
275 new( &place ) A( std::forward< U >( a ) );