Line data Source code
1 : // Copyright (C) 2017 Andrzej Krzemienski. 2 : // 3 : // Use, modification, and distribution is subject to the Boost Software 4 : // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 5 : // http://www.boost.org/LICENSE_1_0.txt) 6 : // 7 : // See http://www.boost.org/libs/optional for documentation. 8 : // 9 : // You are welcome to contact the author at: 10 : // akrzemi1@gmail.com 11 : 12 : // trivially-copyable version of the storage 13 : 14 : template<class T> 15 : class tc_optional_base : public optional_tag 16 : { 17 : private : 18 : 19 : typedef tc_optional_base<T> this_type ; 20 : 21 : protected : 22 : 23 : typedef T value_type ; 24 : 25 : protected: 26 : typedef T & reference_type ; 27 : typedef T const& reference_const_type ; 28 : typedef T && rval_reference_type ; 29 : typedef T && reference_type_of_temporary_wrapper ; 30 : typedef T * pointer_type ; 31 : typedef T const* pointer_const_type ; 32 : typedef T const& argument_type ; 33 : 34 1432 : tc_optional_base() 35 : : 36 1432 : m_initialized(false), m_storage() {} 37 : 38 : tc_optional_base ( none_t ) 39 : : 40 : m_initialized(false), m_storage() {} 41 : 42 : tc_optional_base ( init_value_tag, argument_type val ) 43 : : 44 : m_initialized(true), m_storage(val) {} 45 : 46 : tc_optional_base ( bool cond, argument_type val ) 47 : : 48 : m_initialized(cond), m_storage(val) {} 49 : 50 : // tc_optional_base ( tc_optional_base const& ) = default; 51 : 52 : template<class Expr, class PtrExpr> 53 : explicit tc_optional_base ( Expr&& expr, PtrExpr const* tag ) 54 : : 55 : m_initialized(false) 56 : { 57 : construct(optional_detail::forward<Expr>(expr),tag); 58 : } 59 : 60 : // tc_optional_base& operator= ( tc_optional_base const& ) = default; 61 : // ~tc_optional_base() = default; 62 : 63 : // Assigns from another optional<T> (deep-copies the rhs value) 64 : void assign ( tc_optional_base const& rhs ) 65 : { 66 : *this = rhs; 67 : } 68 : 69 : // Assigns from another _convertible_ optional<U> (deep-copies the rhs value) 70 : template<class U> 71 : void assign ( optional<U> const& rhs ) 72 : { 73 : if ( rhs.is_initialized() ) 74 : #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES 75 : m_storage = rhs.get(); 76 : #else 77 : m_storage = static_cast<value_type>(rhs.get()); 78 : #endif 79 : 80 : m_initialized = rhs.is_initialized(); 81 : } 82 : 83 : // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value) 84 : template<class U> 85 : void assign ( optional<U>&& rhs ) 86 : { 87 : typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type; 88 : if ( rhs.is_initialized() ) 89 : m_storage = static_cast<ref_type>(rhs.get()); 90 : m_initialized = rhs.is_initialized(); 91 : } 92 : 93 8 : void assign ( argument_type val ) 94 : { 95 8 : construct(val); 96 8 : } 97 : 98 : void assign ( none_t ) { destroy(); } 99 : 100 : #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT 101 : 102 : template<class Expr, class ExprPtr> 103 : void assign_expr ( Expr&& expr, ExprPtr const* tag ) 104 : { 105 : construct(optional_detail::forward<Expr>(expr),tag); 106 : } 107 : 108 : #endif 109 : 110 : public : 111 : 112 : // Destroys the current value, if any, leaving this UNINITIALIZED 113 : // No-throw (assuming T::~T() doesn't) 114 4 : void reset() BOOST_NOEXCEPT { destroy(); } 115 : 116 : // **DEPRECATED** Replaces the current value -if any- with 'val' 117 : void reset ( argument_type val ) BOOST_NOEXCEPT { assign(val); } 118 : 119 : // Returns a pointer to the value if this is initialized, otherwise, 120 : // returns NULL. 121 : // No-throw 122 : pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; } 123 : pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } 124 : 125 16 : bool is_initialized() const { return m_initialized ; } 126 : 127 : protected : 128 : 129 8 : void construct ( argument_type val ) 130 : { 131 8 : m_storage = val ; 132 8 : m_initialized = true ; 133 8 : } 134 : 135 : 136 : // Constructs in-place 137 : // upon exception *this is always uninitialized 138 : template<class... Args> 139 : void construct ( in_place_init_t, Args&&... args ) 140 : { 141 : m_storage = value_type( optional_detail::forward<Args>(args)... ) ; 142 : m_initialized = true ; 143 : } 144 : 145 : template<class... Args> 146 : void emplace_assign ( Args&&... args ) 147 : { 148 : construct(in_place_init, optional_detail::forward<Args>(args)...); 149 : } 150 : 151 : template<class... Args> 152 : explicit tc_optional_base ( in_place_init_t, Args&&... args ) 153 : : 154 : m_initialized(false) 155 : { 156 : construct(in_place_init, optional_detail::forward<Args>(args)...); 157 : } 158 : 159 : template<class... Args> 160 : explicit tc_optional_base ( in_place_init_if_t, bool cond, Args&&... args ) 161 : : 162 : m_initialized(false) 163 : { 164 : if ( cond ) 165 : construct(in_place_init, optional_detail::forward<Args>(args)...); 166 : } 167 : 168 : #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT 169 : 170 : // Constructs in-place using the given factory 171 : template<class Expr> 172 : void construct ( Expr&& factory, in_place_factory_base const* ) 173 : { 174 : boost_optional_detail::construct<value_type>(factory, boost::addressof(m_storage)); 175 : m_initialized = true ; 176 : } 177 : 178 : // Constructs in-place using the given typed factory 179 : template<class Expr> 180 : void construct ( Expr&& factory, typed_in_place_factory_base const* ) 181 : { 182 : factory.apply(boost::addressof(m_storage)) ; 183 : m_initialized = true ; 184 : } 185 : 186 : template<class Expr> 187 : void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag ) 188 : { 189 : destroy(); 190 : construct(factory,tag); 191 : } 192 : 193 : // Constructs in-place using the given typed factory 194 : template<class Expr> 195 : void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag ) 196 : { 197 : destroy(); 198 : construct(factory,tag); 199 : } 200 : 201 : #endif 202 : 203 : // Constructs using any expression implicitly convertible to the single argument 204 : // of a one-argument T constructor. 205 : // Converting constructions of optional<T> from optional<U> uses this function with 206 : // 'Expr' being of type 'U' and relying on a converting constructor of T from U. 207 : template<class Expr> 208 : void construct ( Expr&& expr, void const* ) 209 : { 210 : m_storage = value_type(optional_detail::forward<Expr>(expr)) ; 211 : m_initialized = true ; 212 : } 213 : 214 : // Assigns using a form any expression implicitly convertible to the single argument 215 : // of a T's assignment operator. 216 : // Converting assignments of optional<T> from optional<U> uses this function with 217 : // 'Expr' being of type 'U' and relying on a converting assignment of T from U. 218 : template<class Expr> 219 : void assign_expr_to_initialized ( Expr&& expr, void const* ) 220 : { 221 : assign_value( optional_detail::forward<Expr>(expr) ); 222 : } 223 : 224 : #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION 225 : // BCB5.64 (and probably lower versions) workaround. 226 : // The in-place factories are supported by means of catch-all constructors 227 : // and assignment operators (the functions are parameterized in terms of 228 : // an arbitrary 'Expr' type) 229 : // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U> 230 : // to the 'Expr'-taking functions even though explicit overloads are present for them. 231 : // Thus, the following overload is needed to properly handle the case when the 'lhs' 232 : // is another optional. 233 : // 234 : // For VC<=70 compilers this workaround doesn't work because the compiler issues and error 235 : // instead of choosing the wrong overload 236 : // 237 : 238 : // Notice that 'Expr' will be optional<T> or optional<U> (but not tc_optional_base<..>) 239 : template<class Expr> 240 : void construct ( Expr&& expr, optional_tag const* ) 241 : { 242 : if ( expr.is_initialized() ) 243 : { 244 : // An exception can be thrown here. 245 : // It it happens, THIS will be left uninitialized. 246 : m_storage = value_type(optional_detail::move(expr.get())) ; 247 : m_initialized = true ; 248 : } 249 : } 250 : #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION 251 : 252 : void assign_value ( argument_type val ) { m_storage = val; } 253 : void assign_value ( rval_reference_type val ) { m_storage = static_cast<rval_reference_type>(val); } 254 : 255 4 : void destroy() 256 : { 257 4 : m_initialized = false; 258 4 : } 259 : 260 0 : reference_const_type get_impl() const { return m_storage ; } 261 8 : reference_type get_impl() { return m_storage ; } 262 : 263 : pointer_const_type get_ptr_impl() const { return boost::addressof(m_storage); } 264 : pointer_type get_ptr_impl() { return boost::addressof(m_storage); } 265 : 266 : private : 267 : 268 : bool m_initialized ; 269 : T m_storage ; 270 : } ;