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


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Feb 2 2019 03:50:10