optional.hpp
Go to the documentation of this file.
00001 //
00002 // Copyright (c) 2016 Martin Moene
00003 //
00004 // https://github.com/martinmoene/optional-lite
00005 //
00006 // This code is licensed under the MIT License (MIT).
00007 //
00008 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00009 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00010 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00011 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00012 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00013 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00014 // THE SOFTWARE.
00015 
00016 #pragma once
00017 
00018 #ifndef NONSTD_OPTIONAL_LITE_HPP
00019 #define NONSTD_OPTIONAL_LITE_HPP
00020 
00021 #include <cassert>
00022 #include <stdexcept>
00023 #include <utility>
00024 
00025 #define  optional_lite_VERSION "2.0.0"
00026 
00027 // variant-lite alignment configuration:
00028 
00029 #ifndef  optional_CONFIG_MAX_ALIGN_HACK
00030 # define optional_CONFIG_MAX_ALIGN_HACK  0
00031 #endif
00032 
00033 #ifndef  optional_CONFIG_ALIGN_AS
00034 // no default, used in #if defined()
00035 #endif
00036 
00037 #ifndef  optional_CONFIG_ALIGN_AS_FALLBACK
00038 # define optional_CONFIG_ALIGN_AS_FALLBACK  double
00039 #endif
00040 
00041 // Compiler detection (C++17 is speculative):
00042 
00043 #define optional_CPP11_OR_GREATER  ( __cplusplus >= 201103L )
00044 #define optional_CPP14_OR_GREATER  ( __cplusplus >= 201402L )
00045 
00046 // half-open range [lo..hi):
00047 #define optional_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
00048 
00049 #if defined(_MSC_VER) && !defined(__clang__)
00050 # define optional_COMPILER_MSVC_VERSION   (_MSC_VER / 100 - 5 - (_MSC_VER < 1900))
00051 #else
00052 # define optional_COMPILER_MSVC_VERSION   0
00053 #endif
00054 
00055 #if defined __GNUC__
00056 # define optional_COMPILER_GNUC_VERSION  __GNUC__
00057 #else
00058 # define optional_COMPILER_GNUC_VERSION    0
00059 #endif
00060 
00061 #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 7, 14 )
00062 # pragma warning( push )
00063 # pragma warning( disable: 4345 )   // initialization behavior changed
00064 #endif
00065 
00066 #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 7, 15 )
00067 # pragma warning( push )
00068 # pragma warning( disable: 4814 )   // in C++14 'constexpr' will not imply 'const'
00069 #endif
00070 
00071 // Presence of C++11 language features:
00072 
00073 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 10
00074 # define optional_HAVE_AUTO  1
00075 # define optional_HAVE_NULLPTR  1
00076 # define optional_HAVE_STATIC_ASSERT  1
00077 #endif
00078 
00079 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 12
00080 # define optional_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG  1
00081 # define optional_HAVE_INITIALIZER_LIST  1
00082 #endif
00083 
00084 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 14
00085 # define optional_HAVE_ALIAS_TEMPLATE  1
00086 # define optional_HAVE_CONSTEXPR_11  1
00087 # define optional_HAVE_ENUM_CLASS  1
00088 # define optional_HAVE_EXPLICIT_CONVERSION  1
00089 # define optional_HAVE_IS_DEFAULT  1
00090 # define optional_HAVE_IS_DELETE  1
00091 # define optional_HAVE_NOEXCEPT  1
00092 # define optional_HAVE_REF_QUALIFIER  1
00093 #endif
00094 
00095 // Presence of C++14 language features:
00096 
00097 #if optional_CPP14_OR_GREATER
00098 # define optional_HAVE_CONSTEXPR_14  1
00099 #endif
00100 
00101 // Presence of C++ library features:
00102 
00103 #if optional_COMPILER_GNUC_VERSION
00104 # define optional_HAVE_TR1_TYPE_TRAITS  1
00105 # define optional_HAVE_TR1_ADD_POINTER  1
00106 #endif
00107 
00108 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 9
00109 # define optional_HAVE_TYPE_TRAITS  1
00110 # define optional_HAVE_STD_ADD_POINTER  1
00111 #endif
00112 
00113 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 11
00114 # define optional_HAVE_ARRAY  1
00115 #endif
00116 
00117 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 12
00118 # define optional_HAVE_CONDITIONAL  1
00119 #endif
00120 
00121 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 14 || (optional_COMPILER_MSVC_VERSION >= 9 && _HAS_CPP0X)
00122 # define optional_HAVE_CONTAINER_DATA_METHOD  1
00123 #endif
00124 
00125 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 12
00126 # define optional_HAVE_REMOVE_CV  1
00127 #endif
00128 
00129 #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 14
00130 # define optional_HAVE_SIZED_TYPES  1
00131 #endif
00132 
00133 // For the rest, consider VC14 as C++11 for variant-lite:
00134 
00135 #if optional_COMPILER_MSVC_VERSION >= 14
00136 # undef  optional_CPP11_OR_GREATER
00137 # define optional_CPP11_OR_GREATER  1
00138 #endif
00139 
00140 // C++ feature usage:
00141 
00142 #if optional_HAVE_CONSTEXPR_11
00143 # define optional_constexpr  constexpr
00144 #else
00145 # define optional_constexpr  /*constexpr*/
00146 #endif
00147 
00148 #if optional_HAVE_CONSTEXPR_14
00149 # define optional_constexpr14  constexpr
00150 #else
00151 # define optional_constexpr14  /*constexpr*/
00152 #endif
00153 
00154 #if optional_HAVE_NOEXCEPT
00155 # define optional_noexcept  noexcept
00156 #else
00157 # define optional_noexcept  /*noexcept*/
00158 #endif
00159 
00160 #if optional_HAVE_NULLPTR
00161 # define optional_nullptr  nullptr
00162 #else
00163 # define optional_nullptr  NULL
00164 #endif
00165 
00166 #if optional_HAVE_REF_QUALIFIER
00167 # define optional_ref_qual  &
00168 # define optional_refref_qual  &&
00169 #else
00170 # define optional_ref_qual  /*&*/
00171 # define optional_refref_qual  /*&&*/
00172 #endif
00173 
00174 // additional includes:
00175 
00176 #if optional_HAVE_INITIALIZER_LIST
00177 # include <initializer_list>
00178 #endif
00179 
00180 #if optional_HAVE_TYPE_TRAITS
00181 # include <type_traits>
00182 #elif optional_HAVE_TR1_TYPE_TRAITS
00183 # include <tr1/type_traits>
00184 #endif
00185 
00186 //
00187 // in_place: code duplicated in any-lite, optional-lite, variant-lite:
00188 //
00189 
00190 #if ! nonstd_lite_HAVE_IN_PLACE_TYPES
00191 
00192 namespace nonstd {
00193 
00194 namespace detail {
00195 
00196 template< class T >
00197 struct in_place_type_tag {};
00198 
00199 template< std::size_t I >
00200 struct in_place_index_tag {};
00201 
00202 } // namespace detail
00203 
00204 struct in_place_t {};
00205 
00206 template< class T >
00207 inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
00208 {
00209     return in_place_t();
00210 }
00211 
00212 template< std::size_t I >
00213 inline in_place_t in_place( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() )
00214 {
00215     return in_place_t();
00216 }
00217 
00218 // mimic templated typedef:
00219 
00220 #define nonstd_lite_in_place_type_t( T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
00221 #define nonstd_lite_in_place_index_t(T)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<I> )
00222 
00223 #define nonstd_lite_HAVE_IN_PLACE_TYPES  1
00224 
00225 } // namespace nonstd
00226 
00227 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
00228 
00229 //
00230 // optional:
00231 //
00232 
00233 namespace nonstd { namespace optional_lite {
00234 
00236 
00237 template< typename T >
00238 class optional;
00239 
00240 namespace detail {
00241 
00242 // C++11 emulation:
00243 
00244 #if variant_HAVE_CONDITIONAL
00245 
00246 using std::conditional;
00247 
00248 #else
00249 
00250 template< bool Cond, class Then, class Else >
00251 struct conditional;
00252 
00253 template< class Then, class Else >
00254 struct conditional< true , Then, Else > { typedef Then type; };
00255 
00256 template< class Then, class Else >
00257 struct conditional< false, Then, Else > { typedef Else type; };
00258 
00259 #endif // variant_HAVE_CONDITIONAL
00260 
00261 struct nulltype{};
00262 
00263 template< typename Head, typename Tail >
00264 struct typelist
00265 {
00266     typedef Head head;
00267     typedef Tail tail;
00268 };
00269 
00270 #if optional_CONFIG_MAX_ALIGN_HACK
00271 
00272 // Max align, use most restricted type for alignment:
00273 
00274 #define optional_UNIQUE(  name )       optional_UNIQUE2( name, __LINE__ )
00275 #define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
00276 #define optional_UNIQUE3( name, line ) name ## line
00277 
00278 #define optional_ALIGN_TYPE( type ) \
00279     type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
00280 
00281 template< typename T >
00282 struct struct_t { T _; };
00283 
00284 union max_align_t
00285 {
00286     optional_ALIGN_TYPE( char );
00287     optional_ALIGN_TYPE( short int );
00288     optional_ALIGN_TYPE( int );
00289     optional_ALIGN_TYPE( long int  );
00290     optional_ALIGN_TYPE( float  );
00291     optional_ALIGN_TYPE( double );
00292     optional_ALIGN_TYPE( long double );
00293     optional_ALIGN_TYPE( char * );
00294     optional_ALIGN_TYPE( short int * );
00295     optional_ALIGN_TYPE( int *  );
00296     optional_ALIGN_TYPE( long int * );
00297     optional_ALIGN_TYPE( float * );
00298     optional_ALIGN_TYPE( double * );
00299     optional_ALIGN_TYPE( long double * );
00300     optional_ALIGN_TYPE( void * );
00301 
00302 #ifdef HAVE_LONG_LONG
00303     optional_ALIGN_TYPE( long long );
00304 #endif
00305 
00306     struct Unknown;
00307 
00308     Unknown ( * optional_UNIQUE(_) )( Unknown );
00309     Unknown * Unknown::* optional_UNIQUE(_);
00310     Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
00311 
00312     struct_t< Unknown ( * )( Unknown)         > optional_UNIQUE(_);
00313     struct_t< Unknown * Unknown::*            > optional_UNIQUE(_);
00314     struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
00315 };
00316 
00317 #undef optional_UNIQUE
00318 #undef optional_UNIQUE2
00319 #undef optional_UNIQUE3
00320 
00321 #undef optional_ALIGN_TYPE
00322 
00323 #elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
00324 
00325 // Use user-specified type for alignment:
00326 
00327 #define optional_ALIGN_AS( unused ) \
00328     optional_CONFIG_ALIGN_AS
00329 
00330 #else // optional_CONFIG_MAX_ALIGN_HACK
00331 
00332 // Determine POD type to use for alignment:
00333 
00334 #define optional_ALIGN_AS( to_align ) \
00335     typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
00336 
00337 template <typename T>
00338 struct alignment_of;
00339 
00340 template <typename T>
00341 struct alignment_of_hack
00342 {
00343     char c;
00344     T t;
00345     alignment_of_hack();
00346 };
00347 
00348 template <unsigned A, unsigned S>
00349 struct alignment_logic
00350 {
00351     enum { value = A < S ? A : S };
00352 };
00353 
00354 template< typename T >
00355 struct alignment_of
00356 {
00357     enum { value = alignment_logic<
00358         sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value, };
00359 };
00360 
00361 template< typename List, size_t N >
00362 struct type_of_size
00363 {
00364     typedef typename conditional<
00365         N == sizeof( typename List::head ),
00366             typename List::head,
00367             typename type_of_size<typename List::tail, N >::type >::type type;
00368 };
00369 
00370 template< size_t N >
00371 struct type_of_size< nulltype, N >
00372 {
00373     typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
00374 };
00375 
00376 template< typename T>
00377 struct struct_t { T _; };
00378 
00379 #define optional_ALIGN_TYPE( type ) \
00380     typelist< type , typelist< struct_t< type >
00381 
00382 struct Unknown;
00383 
00384 typedef
00385     optional_ALIGN_TYPE( char ),
00386     optional_ALIGN_TYPE( short ),
00387     optional_ALIGN_TYPE( int ),
00388     optional_ALIGN_TYPE( long ),
00389     optional_ALIGN_TYPE( float ),
00390     optional_ALIGN_TYPE( double ),
00391     optional_ALIGN_TYPE( long double ),
00392 
00393     optional_ALIGN_TYPE( char *),
00394     optional_ALIGN_TYPE( short * ),
00395     optional_ALIGN_TYPE( int * ),
00396     optional_ALIGN_TYPE( long * ),
00397     optional_ALIGN_TYPE( float * ),
00398     optional_ALIGN_TYPE( double * ),
00399     optional_ALIGN_TYPE( long double * ),
00400 
00401     optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
00402     optional_ALIGN_TYPE( Unknown * Unknown::*     ),
00403     optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
00404 
00405     nulltype
00406     > > > > > > >    > > > > > > >
00407     > > > > > > >    > > > > > > >
00408     > > > > > >
00409     alignment_types;
00410 
00411 #undef optional_ALIGN_TYPE
00412 
00413 #endif // optional_CONFIG_MAX_ALIGN_HACK
00414 
00416 
00417 template< typename T >
00418 union storage_t
00419 {
00420 private:
00421     friend class optional<T>;
00422 
00423     typedef T value_type;
00424 
00425     storage_t() {}
00426 
00427     storage_t( value_type const & v )
00428     {
00429         construct_value( v );
00430     }
00431 
00432     void construct_value( value_type const & v )
00433     {
00434         ::new( value_ptr() ) value_type( v );
00435     }
00436 
00437 #if optional_CPP11_OR_GREATER
00438 
00439     storage_t( value_type && v )
00440     {
00441         construct_value( std::move( v ) );
00442     }
00443 
00444     void construct_value( value_type && v )
00445     {
00446         ::new( value_ptr() ) value_type( std::move( v ) );
00447     }
00448 
00449 #endif
00450 
00451     void destruct_value()
00452     {
00453         value_ptr()->~T();
00454     }
00455 
00456     value_type const * value_ptr() const
00457     {
00458         return as<value_type>();
00459     }
00460 
00461     value_type * value_ptr()
00462     {
00463         return as<value_type>();
00464     }
00465 
00466     value_type const & value() const optional_ref_qual
00467     {
00468         return * value_ptr();
00469     }
00470 
00471     value_type & value() optional_ref_qual
00472     {
00473         return * value_ptr();
00474     }
00475 
00476 #if optional_CPP11_OR_GREATER
00477 
00478     value_type const && value() const optional_refref_qual
00479     {
00480         return * value_ptr();
00481     }
00482 
00483     value_type && value() optional_refref_qual
00484     {
00485         return * value_ptr();
00486     }
00487 
00488 #endif
00489 
00490 #if optional_CPP11_OR_GREATER
00491 
00492     using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
00493     aligned_storage_t data;
00494 
00495 #elif optional_CONFIG_MAX_ALIGN_HACK
00496 
00497     typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
00498 
00499     max_align_t hack;
00500     aligned_storage_t data;
00501 
00502 #else
00503     typedef optional_ALIGN_AS(value_type) align_as_type;
00504 
00505     typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
00506     aligned_storage_t data;
00507 
00508 #   undef optional_ALIGN_AS
00509 
00510 #endif // optional_CONFIG_MAX_ALIGN_HACK
00511 
00512     void * ptr() optional_noexcept
00513     {
00514         return &data;
00515     }
00516 
00517     void const * ptr() const optional_noexcept
00518     {
00519         return &data;
00520     }
00521 
00522     template <typename U>
00523     U * as()
00524     {
00525         return reinterpret_cast<U*>( ptr() );
00526     }
00527 
00528     template <typename U>
00529     U const * as() const
00530     {
00531         return reinterpret_cast<U const *>( ptr() );
00532     }
00533 };
00534 
00535 } // namespace detail
00536 
00538 
00539 struct nullopt_t
00540 {
00541     struct init{};
00542     optional_constexpr nullopt_t( init ) {}
00543 };
00544 
00545 #if optional_HAVE_CONSTEXPR_11
00546 constexpr nullopt_t nullopt{ nullopt_t::init{} };
00547 #else
00548 // extra parenthesis to prevent the most vexing parse:
00549 const nullopt_t nullopt(( nullopt_t::init() ));
00550 #endif
00551 
00553 
00554 class bad_optional_access : public std::logic_error
00555 {
00556 public:
00557   explicit bad_optional_access()
00558   : logic_error( "bad optional access" ) {}
00559 };
00560 
00562 
00563 template< typename T>
00564 class optional
00565 {
00566 private:
00567     typedef void (optional::*safe_bool)() const;
00568 
00569 public:
00570     typedef T value_type;
00571 
00572     optional_constexpr optional() optional_noexcept
00573     : has_value_( false )
00574     , contained()
00575     {}
00576 
00577     optional_constexpr optional( nullopt_t ) optional_noexcept
00578     : has_value_( false )
00579     , contained()
00580     {}
00581 
00582     optional( optional const & rhs )
00583     : has_value_( rhs.has_value() )
00584     {
00585         if ( rhs.has_value() )
00586             contained.construct_value( rhs.contained.value() );
00587     }
00588 
00589 #if optional_CPP11_OR_GREATER
00590     optional_constexpr14 optional( optional && rhs ) noexcept( std::is_nothrow_move_constructible<T>::value )
00591     : has_value_( rhs.has_value() )
00592     {
00593         if ( rhs.has_value() )
00594             contained.construct_value( std::move( rhs.contained.value() ) );
00595     }
00596 #endif
00597 
00598     optional_constexpr optional( value_type const & value )
00599     : has_value_( true )
00600     , contained( value )
00601     {}
00602 
00603 #if optional_CPP11_OR_GREATER
00604 
00605     optional_constexpr optional( value_type && value )
00606     : has_value_( true )
00607     , contained( std::move( value ) )
00608     {}
00609 
00610     template< class... Args >
00611     optional_constexpr explicit optional( nonstd_lite_in_place_type_t(T), Args&&... args )
00612     : has_value_( true )
00613     , contained( T( std::forward<Args>(args)...) )
00614     {}
00615 
00616     template< class U, class... Args >
00617     optional_constexpr explicit optional( nonstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
00618     : has_value_( true )
00619     , contained( T( il, std::forward<Args>(args)...) )
00620     {}
00621 
00622 #endif // optional_CPP11_OR_GREATER
00623 
00624     ~optional()
00625     {
00626         if ( has_value() )
00627             contained.destruct_value();
00628     }
00629 
00630     // assignment
00631 
00632     optional & operator=( nullopt_t ) optional_noexcept
00633     {
00634         reset();
00635         return *this;
00636     }
00637 
00638     optional & operator=( optional const & rhs )
00639 #if optional_CPP11_OR_GREATER
00640         noexcept( std::is_nothrow_move_assignable<T>::value && std::is_nothrow_move_constructible<T>::value )
00641 #endif
00642     {
00643         if      ( has_value() == true  && rhs.has_value() == false ) reset();
00644         else if ( has_value() == false && rhs.has_value() == true  ) initialize( *rhs );
00645         else if ( has_value() == true  && rhs.has_value() == true  ) contained.value() = *rhs;
00646         return *this;
00647     }
00648 
00649 #if optional_CPP11_OR_GREATER
00650 
00651     optional & operator=( optional && rhs ) noexcept
00652     {
00653         if      ( has_value() == true  && rhs.has_value() == false ) reset();
00654         else if ( has_value() == false && rhs.has_value() == true  ) initialize( std::move( *rhs ) );
00655         else if ( has_value() == true  && rhs.has_value() == true  ) contained.value() = std::move( *rhs );
00656         return *this;
00657     }
00658 
00659     template< class U,
00660         typename = typename std::enable_if< std::is_same< typename std::decay<U>::type, T>::value >::type >
00661     optional & operator=( U && v )
00662     {
00663         if ( has_value() ) contained.value() = std::forward<U>( v );
00664         else               initialize( T( std::forward<U>( v ) ) );
00665         return *this;
00666     }
00667 
00668     template< class... Args >
00669     void emplace( Args&&... args )
00670     {
00671         *this = nullopt;
00672         initialize( T( std::forward<Args>(args)...) );
00673     }
00674 
00675     template< class U, class... Args >
00676     void emplace( std::initializer_list<U> il, Args&&... args )
00677     {
00678         *this = nullopt;
00679         initialize( T( il, std::forward<Args>(args)...) );
00680     }
00681 
00682 #endif // optional_CPP11_OR_GREATER
00683 
00684     // swap
00685 
00686     void swap( optional & rhs )
00687 #if optional_CPP11_OR_GREATER
00688     noexcept( std::is_nothrow_move_constructible<T>::value && noexcept( std::swap( std::declval<T&>(), std::declval<T&>() ) ) )
00689 #endif
00690     {
00691         using std::swap;
00692         if      ( has_value() == true  && rhs.has_value() == true  ) { swap( **this, *rhs ); }
00693         else if ( has_value() == false && rhs.has_value() == true  ) { initialize( *rhs ); rhs.reset(); }
00694         else if ( has_value() == true  && rhs.has_value() == false ) { rhs.initialize( **this ); reset(); }
00695     }
00696 
00697     // observers
00698 
00699     optional_constexpr value_type const * operator ->() const
00700     {
00701         return assert( has_value() ),
00702             contained.value_ptr();
00703     }
00704 
00705     optional_constexpr14 value_type * operator ->()
00706     {
00707         return assert( has_value() ),
00708             contained.value_ptr();
00709     }
00710 
00711     optional_constexpr value_type const & operator *() const optional_ref_qual
00712     {
00713         return assert( has_value() ),
00714             contained.value();
00715     }
00716 
00717     optional_constexpr14 value_type & operator *() optional_ref_qual
00718     {
00719         return assert( has_value() ),
00720             contained.value();
00721     }
00722 
00723 #if optional_CPP11_OR_GREATER
00724 
00725     optional_constexpr value_type const && operator *() const optional_refref_qual
00726     {
00727         assert( has_value() );
00728         return std::move( contained.value() );
00729     }
00730 
00731     optional_constexpr14 value_type && operator *() optional_refref_qual
00732     {
00733         assert( has_value() );
00734         return std::move( contained.value() );
00735     }
00736 
00737 #endif
00738 
00739 #if optional_CPP11_OR_GREATER
00740     optional_constexpr explicit operator bool() const optional_noexcept
00741     {
00742         return has_value();
00743     }
00744 #else
00745     optional_constexpr operator safe_bool() const optional_noexcept
00746     {
00747         return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
00748     }
00749 #endif
00750 
00751     optional_constexpr bool has_value() const optional_noexcept
00752     {
00753         return has_value_;
00754     }
00755 
00756     optional_constexpr14 value_type const & value() const optional_ref_qual
00757     {
00758         if ( ! has_value() )
00759             throw bad_optional_access();
00760 
00761         return contained.value();
00762     }
00763 
00764     optional_constexpr14 value_type & value() optional_ref_qual
00765     {
00766         if ( ! has_value() )
00767             throw bad_optional_access();
00768 
00769         return contained.value();
00770     }
00771 
00772 #if optional_HAVE_REF_QUALIFIER
00773 
00774     optional_constexpr14 value_type const && value() const optional_refref_qual
00775     {
00776         if ( ! has_value() )
00777             throw bad_optional_access();
00778 
00779         return std::move( contained.value() );
00780     }
00781 
00782     optional_constexpr14 value_type && value() optional_refref_qual
00783     {
00784         if ( ! has_value() )
00785             throw bad_optional_access();
00786 
00787         return std::move( contained.value() );
00788     }
00789 
00790 #endif
00791 
00792 #if optional_CPP11_OR_GREATER
00793 
00794     template< class U >
00795     optional_constexpr value_type value_or( U && v ) const optional_ref_qual
00796     {
00797         return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
00798     }
00799 
00800     template< class U >
00801     optional_constexpr value_type value_or( U && v ) const optional_refref_qual
00802     {
00803         return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
00804     }
00805 
00806 #else
00807 
00808     template< class U >
00809     optional_constexpr value_type value_or( U const & v ) const
00810     {
00811         return has_value() ? contained.value() : static_cast<value_type>( v );
00812     }
00813 
00814 #endif // optional_CPP11_OR_GREATER
00815 
00816     // modifiers
00817 
00818     void reset() optional_noexcept
00819     {
00820         if ( has_value() )
00821             contained.destruct_value();
00822 
00823         has_value_ = false;
00824     }
00825 
00826 private:
00827     void this_type_does_not_support_comparisons() const {}
00828 
00829     template< typename V >
00830     void initialize( V const & value )
00831     {
00832         assert( ! has_value()  );
00833         contained.construct_value( value );
00834         has_value_ = true;
00835     }
00836 
00837 #if optional_CPP11_OR_GREATER
00838     template< typename V >
00839     void initialize( V && value )
00840     {
00841         assert( ! has_value()  );
00842         contained.construct_value( std::move( value ) );
00843         has_value_ = true;
00844     }
00845 #endif
00846 
00847 private:
00848     bool has_value_;
00849     detail::storage_t< value_type > contained;
00850 
00851 };
00852 
00853 // Relational operators
00854 
00855 template< typename T > bool operator==( optional<T> const & x, optional<T> const & y )
00856 {
00857     return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
00858 }
00859 
00860 template< typename T > bool operator!=( optional<T> const & x, optional<T> const & y )
00861 {
00862     return !(x == y);
00863 }
00864 
00865 template< typename T > bool operator<( optional<T> const & x, optional<T> const & y )
00866 {
00867     return (!y) ? false : (!x) ? true : *x < *y;
00868 }
00869 
00870 template< typename T > bool operator>( optional<T> const & x, optional<T> const & y )
00871 {
00872     return (y < x);
00873 }
00874 
00875 template< typename T > bool operator<=( optional<T> const & x, optional<T> const & y )
00876 {
00877     return !(y < x);
00878 }
00879 
00880 template< typename T > bool operator>=( optional<T> const & x, optional<T> const & y )
00881 {
00882     return !(x < y);
00883 }
00884 
00885 // Comparison with nullopt
00886 
00887 template< typename T > bool operator==( optional<T> const & x, nullopt_t ) optional_noexcept
00888 {
00889     return (!x);
00890 }
00891 
00892 template< typename T > bool operator==( nullopt_t, optional<T> const & x ) optional_noexcept
00893 {
00894     return (!x);
00895 }
00896 
00897 template< typename T > bool operator!=( optional<T> const & x, nullopt_t ) optional_noexcept
00898 {
00899     return bool(x);
00900 }
00901 
00902 template< typename T > bool operator!=( nullopt_t, optional<T> const & x ) optional_noexcept
00903 {
00904     return bool(x);
00905 }
00906 
00907 template< typename T > bool operator<( optional<T> const &, nullopt_t ) optional_noexcept
00908 {
00909     return false;
00910 }
00911 
00912 template< typename T > bool operator<( nullopt_t, optional<T> const & x ) optional_noexcept
00913 {
00914     return bool(x);
00915 }
00916 
00917 template< typename T > bool operator<=( optional<T> const & x, nullopt_t ) optional_noexcept
00918 {
00919     return (!x);
00920 }
00921 
00922 template< typename T > bool operator<=( nullopt_t, optional<T> const & ) optional_noexcept
00923 {
00924     return true;
00925 }
00926 
00927 template< typename T > bool operator>( optional<T> const & x, nullopt_t ) optional_noexcept
00928 {
00929     return bool(x);
00930 }
00931 
00932 template< typename T > bool operator>( nullopt_t, optional<T> const & ) optional_noexcept
00933 {
00934     return false;
00935 }
00936 
00937 template< typename T > bool operator>=( optional<T> const &, nullopt_t )
00938 {
00939     return true;
00940 }
00941 
00942 template< typename T > bool operator>=( nullopt_t, optional<T> const & x )
00943 {
00944     return (!x);
00945 }
00946 
00947 // Comparison with T
00948 
00949 template< typename T > bool operator==( optional<T> const & x, const T& v )
00950 {
00951     return bool(x) ? *x == v : false;
00952 }
00953 
00954 template< typename T > bool operator==( T const & v, optional<T> const & x )
00955 {
00956     return bool(x) ? v == *x : false;
00957 }
00958 
00959 template< typename T > bool operator!=( optional<T> const & x, const T& v )
00960 {
00961     return bool(x) ? *x != v : true;
00962 }
00963 
00964 template< typename T > bool operator!=( T const & v, optional<T> const & x )
00965 {
00966     return bool(x) ? v != *x : true;
00967 }
00968 
00969 template< typename T > bool operator<( optional<T> const & x, const T& v )
00970 {
00971     return bool(x) ? *x < v : true;
00972 }
00973 
00974 template< typename T > bool operator<( T const & v, optional<T> const & x )
00975 {
00976     return bool(x) ? v < *x : false;
00977 }
00978 
00979 template< typename T > bool operator<=( optional<T> const & x, const T& v )
00980 {
00981     return bool(x) ? *x <= v : true;
00982 }
00983 
00984 template< typename T > bool operator<=( T const & v, optional<T> const & x )
00985 {
00986     return bool(x) ? v <= *x : false;
00987 }
00988 
00989 template< typename T > bool operator>( optional<T> const & x, const T& v )
00990 {
00991     return bool(x) ? *x > v : false;
00992 }
00993 
00994 template< typename T > bool operator>( T const & v, optional<T> const & x )
00995 {
00996     return bool(x) ? v > *x : true;
00997 }
00998 
00999 template< typename T > bool operator>=( optional<T> const & x, const T& v )
01000 {
01001     return bool(x) ? *x >= v : false;
01002 }
01003 
01004 template< typename T > bool operator>=( T const & v, optional<T> const & x )
01005 {
01006     return bool(x) ? v >= *x : true;
01007 }
01008 
01009 // Specialized algorithms
01010 
01011 template< typename T >
01012 void swap( optional<T> & x, optional<T> & y )
01013 #if optional_CPP11_OR_GREATER
01014     noexcept( noexcept( x.swap(y) ) )
01015 #endif
01016 {
01017     x.swap( y );
01018 }
01019 
01020 #if optional_CPP11_OR_GREATER
01021 
01022 template< class T >
01023 optional_constexpr optional< typename std::decay<T>::type > make_optional( T && v )
01024 {
01025     return optional< typename std::decay<T>::type >( std::forward<T>( v ) );
01026 }
01027 
01028 template< class T, class...Args >
01029 optional_constexpr optional<T> make_optional( Args&&... args )
01030 {
01031     return optional<T>( in_place, std::forward<Args>(args)...);
01032 }
01033 
01034 template< class T, class U, class... Args >
01035 optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
01036 {
01037     return optional<T>( in_place, il, std::forward<Args>(args)...);
01038 }
01039 
01040 #else
01041 
01042 template< typename T >
01043 optional<T> make_optional( T const & v )
01044 {
01045     return optional<T>( v );
01046 }
01047 
01048 #endif // optional_CPP11_OR_GREATER
01049 
01050 } // namespace optional
01051 
01052 using namespace optional_lite;
01053 
01054 } // namespace nonstd
01055 
01056 #if optional_CPP11_OR_GREATER
01057 
01058 // specialize the std::hash algorithm:
01059 
01060 namespace std {
01061 
01062 template< class T >
01063 class hash< nonstd::optional<T> >
01064 {
01065 public:
01066     std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
01067     {
01068         return bool( v ) ? hash<T>()( *v ) : 0;
01069     }
01070 };
01071 
01072 } //namespace std
01073 
01074 #endif // optional_CPP11_OR_GREATER
01075 
01076 #endif // NONSTD_OPTIONAL_LITE_HPP


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56