| // |
| // Copyright (c) 2014-2018 Martin Moene |
| // |
| // https://github.com/martinmoene/optional-lite |
| // |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| #pragma once |
| |
| #ifndef NONSTD_OPTIONAL_LITE_HPP |
| #define NONSTD_OPTIONAL_LITE_HPP |
| |
| #define optional_lite_MAJOR 3 |
| #define optional_lite_MINOR 1 |
| #define optional_lite_PATCH 0 |
| |
| #define optional_lite_VERSION optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH) |
| |
| #define optional_STRINGIFY( x ) optional_STRINGIFY_( x ) |
| #define optional_STRINGIFY_( x ) #x |
| |
| // optional-lite configuration: |
| |
| #define optional_OPTIONAL_DEFAULT 0 |
| #define optional_OPTIONAL_NONSTD 1 |
| #define optional_OPTIONAL_STD 2 |
| |
| #if !defined( optional_CONFIG_SELECT_OPTIONAL ) |
| # define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD ) |
| #endif |
| |
| // C++ language version detection (C++20 is speculative): |
| // Note: VC14.0/1900 (VS2015) lacks too much from C++14. |
| |
| #ifndef optional_CPLUSPLUS |
| # ifdef _MSVC_LANG |
| # define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) |
| # else |
| # define optional_CPLUSPLUS __cplusplus |
| # endif |
| #endif |
| |
| #define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L ) |
| #define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L ) |
| #define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L ) |
| #define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L ) |
| #define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L ) |
| |
| // C++ language version (represent 98 as 3): |
| |
| #define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) ) |
| |
| // Use C++17 std::optional if available and requested: |
| |
| #if optional_CPP17_OR_GREATER && defined(__has_include ) |
| # if __has_include( <optional> ) |
| # define optional_HAVE_STD_OPTIONAL 1 |
| # else |
| # define optional_HAVE_STD_OPTIONAL 0 |
| # endif |
| #else |
| # define optional_HAVE_STD_OPTIONAL 0 |
| #endif |
| |
| #define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) ) |
| |
| // Using std::optional: |
| |
| #if optional_USES_STD_OPTIONAL |
| |
| #include <optional> |
| |
| namespace nonstd { |
| |
| using std::optional; |
| using std::bad_optional_access; |
| using std::hash; |
| |
| using std::nullopt; |
| using std::nullopt_t; |
| using std::in_place; |
| using std::in_place_type; |
| using std::in_place_index; |
| using std::in_place_t; |
| using std::in_place_type_t; |
| using std::in_place_index_t; |
| |
| using std::operator==; |
| using std::operator!=; |
| using std::operator<; |
| using std::operator<=; |
| using std::operator>; |
| using std::operator>=; |
| using std::make_optional; |
| using std::swap; |
| } |
| |
| #else // optional_USES_STD_OPTIONAL |
| |
| #include <cassert> |
| #include <stdexcept> |
| #include <utility> |
| |
| // optional-lite alignment configuration: |
| |
| #ifndef optional_CONFIG_MAX_ALIGN_HACK |
| # define optional_CONFIG_MAX_ALIGN_HACK 0 |
| #endif |
| |
| #ifndef optional_CONFIG_ALIGN_AS |
| // no default, used in #if defined() |
| #endif |
| |
| #ifndef optional_CONFIG_ALIGN_AS_FALLBACK |
| # define optional_CONFIG_ALIGN_AS_FALLBACK double |
| #endif |
| |
| // Compiler warning suppression: |
| |
| #if defined (__clang__) |
| # pragma clang diagnostic push |
| # pragma clang diagnostic ignored "-Wundef" |
| #elif defined (__GNUC__) |
| # pragma GCC diagnostic push |
| # pragma GCC diagnostic ignored "-Wundef" |
| #endif |
| |
| // half-open range [lo..hi): |
| #define optional_BETWEEN( v, lo, hi ) ( lo <= v && v < hi ) |
| |
| #if defined(_MSC_VER) && !defined(__clang__) |
| # define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) ) |
| #else |
| # define optional_COMPILER_MSVC_VERSION 0 |
| #endif |
| |
| #define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * major + minor ) + patch ) |
| |
| #if defined (__GNUC__) && !defined(__clang__) |
| # define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) |
| #else |
| # define optional_COMPILER_GNUC_VERSION 0 |
| #endif |
| |
| #if defined (__clang__) |
| # define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) |
| #else |
| # define optional_COMPILER_CLANG_VERSION 0 |
| #endif |
| |
| #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 ) |
| # pragma warning( push ) |
| # pragma warning( disable: 4345 ) // initialization behavior changed |
| #endif |
| |
| #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 ) |
| # pragma warning( push ) |
| # pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const' |
| #endif |
| |
| // Presence of language and library features: |
| |
| #define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE ) |
| |
| // Presence of C++11 language features: |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 100 |
| # define optional_HAVE_AUTO 1 |
| # define optional_HAVE_NULLPTR 1 |
| # define optional_HAVE_STATIC_ASSERT 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 120 |
| # define optional_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG 1 |
| # define optional_HAVE_INITIALIZER_LIST 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 140 |
| # define optional_HAVE_ALIAS_TEMPLATE 1 |
| # define optional_HAVE_CONSTEXPR_11 1 |
| # define optional_HAVE_ENUM_CLASS 1 |
| # define optional_HAVE_EXPLICIT_CONVERSION 1 |
| # define optional_HAVE_IS_DEFAULT 1 |
| # define optional_HAVE_IS_DELETE 1 |
| # define optional_HAVE_NOEXCEPT 1 |
| # define optional_HAVE_REF_QUALIFIER 1 |
| #endif |
| |
| // Presence of C++14 language features: |
| |
| #if optional_CPP14_OR_GREATER |
| # define optional_HAVE_CONSTEXPR_14 1 |
| #endif |
| |
| // Presence of C++17 language features: |
| |
| #if optional_CPP17_OR_GREATER |
| # define optional_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE 1 |
| #endif |
| |
| // Presence of C++ library features: |
| |
| #if optional_COMPILER_GNUC_VERSION |
| # define optional_HAVE_TR1_TYPE_TRAITS 1 |
| # define optional_HAVE_TR1_ADD_POINTER 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 90 |
| # define optional_HAVE_TYPE_TRAITS 1 |
| # define optional_HAVE_STD_ADD_POINTER 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 110 |
| # define optional_HAVE_ARRAY 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 120 |
| # define optional_HAVE_CONDITIONAL 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 140 || (optional_COMPILER_MSVC_VERSION >= 90 && _HAS_CPP0X) |
| # define optional_HAVE_CONTAINER_DATA_METHOD 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 120 |
| # define optional_HAVE_REMOVE_CV 1 |
| #endif |
| |
| #if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 140 |
| # define optional_HAVE_SIZED_TYPES 1 |
| #endif |
| |
| // For the rest, consider VC14 as C++11 for optional-lite: |
| |
| #if optional_COMPILER_MSVC_VERSION >= 140 |
| # undef optional_CPP11_OR_GREATER |
| # define optional_CPP11_OR_GREATER 1 |
| #endif |
| |
| // C++ feature usage: |
| |
| #if optional_HAVE( CONSTEXPR_11 ) |
| # define optional_constexpr constexpr |
| #else |
| # define optional_constexpr /*constexpr*/ |
| #endif |
| |
| #if optional_HAVE( CONSTEXPR_14 ) |
| # define optional_constexpr14 constexpr |
| #else |
| # define optional_constexpr14 /*constexpr*/ |
| #endif |
| |
| #if optional_HAVE( NOEXCEPT ) |
| # define optional_noexcept noexcept |
| #else |
| # define optional_noexcept /*noexcept*/ |
| #endif |
| |
| #if optional_HAVE( NULLPTR ) |
| # define optional_nullptr nullptr |
| #else |
| # define optional_nullptr NULL |
| #endif |
| |
| #if optional_HAVE( REF_QUALIFIER ) |
| # define optional_ref_qual & |
| # define optional_refref_qual && |
| #else |
| # define optional_ref_qual /*&*/ |
| # define optional_refref_qual /*&&*/ |
| #endif |
| |
| // additional includes: |
| |
| #if optional_CPP11_OR_GREATER |
| # include <functional> |
| #endif |
| |
| #if optional_HAVE( INITIALIZER_LIST ) |
| # include <initializer_list> |
| #endif |
| |
| #if optional_HAVE( TYPE_TRAITS ) |
| # include <type_traits> |
| #elif optional_HAVE( TR1_TYPE_TRAITS ) |
| # include <tr1/type_traits> |
| #endif |
| |
| // Method enabling |
| |
| #if optional_CPP11_OR_GREATER |
| |
| # define optional_REQUIRES_T(...) \ |
| , typename = typename std::enable_if<__VA_ARGS__>::type |
| |
| # define optional_REQUIRES_R(R, ...) \ |
| typename std::enable_if<__VA_ARGS__, R>::type |
| |
| # define optional_REQUIRES_A(...) \ |
| , typename std::enable_if<__VA_ARGS__, void*>::type = optional_nullptr |
| |
| #endif |
| |
| // |
| // in_place: code duplicated in any-lite, expected-lite, optional-lite, variant-lite: |
| // |
| |
| #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES |
| #define nonstd_lite_HAVE_IN_PLACE_TYPES 1 |
| |
| // C++17 std::in_place in <utility>: |
| |
| #if optional_CPP17_OR_GREATER |
| |
| namespace nonstd { |
| |
| using std::in_place; |
| using std::in_place_type; |
| using std::in_place_index; |
| using std::in_place_t; |
| using std::in_place_type_t; |
| using std::in_place_index_t; |
| |
| #define nonstd_lite_in_place_t( T) std::in_place_t |
| #define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T> |
| #define nonstd_lite_in_place_index_t(T) std::in_place_index_t<I> |
| |
| #define nonstd_lite_in_place( T) std::in_place_t{} |
| #define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{} |
| #define nonstd_lite_in_place_index(T) std::in_place_index_t<I>{} |
| |
| } // namespace nonstd |
| |
| #else // optional_CPP17_OR_GREATER |
| |
| namespace nonstd { |
| namespace detail { |
| |
| template< class T > |
| struct in_place_type_tag {}; |
| |
| template< std::size_t I > |
| struct in_place_index_tag {}; |
| |
| } // namespace detail |
| |
| struct in_place_t {}; |
| |
| template< class T > |
| inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() ) |
| { |
| return in_place_t(); |
| } |
| |
| template< std::size_t I > |
| inline in_place_t in_place( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() ) |
| { |
| return in_place_t(); |
| } |
| |
| template< class T > |
| inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() ) |
| { |
| return in_place_t(); |
| } |
| |
| template< std::size_t I > |
| inline in_place_t in_place_index( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() ) |
| { |
| return in_place_t(); |
| } |
| |
| // mimic templated typedef: |
| |
| #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) |
| #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) |
| #define nonstd_lite_in_place_index_t(T) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<I> ) |
| |
| #define nonstd_lite_in_place( T) nonstd::in_place_type<T> |
| #define nonstd_lite_in_place_type( T) nonstd::in_place_type<T> |
| #define nonstd_lite_in_place_index(T) nonstd::in_place_index<I> |
| |
| } // namespace nonstd |
| |
| #endif // optional_CPP17_OR_GREATER |
| #endif // nonstd_lite_HAVE_IN_PLACE_TYPES |
| |
| // |
| // optional: |
| // |
| |
| namespace nonstd { namespace optional_lite { |
| |
| namespace detail { |
| |
| #if optional_HAVE( CONDITIONAL ) |
| using std::conditional; |
| #else |
| template< bool B, typename T, typename F > struct conditional { typedef T type; }; |
| template< typename T, typename F > struct conditional<false, T, F> { typedef F type; }; |
| #endif // optional_HAVE_CONDITIONAL |
| |
| } // namespace detail |
| |
| #if optional_CPP11_OR_GREATER |
| |
| namespace std20 { |
| |
| // type traits C++20: |
| |
| template< typename T > |
| struct remove_cvref |
| { |
| typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type; |
| }; |
| |
| } // namespace std20 |
| |
| #endif // optional_CPP11_OR_GREATER |
| |
| /// class optional |
| |
| template< typename T > |
| class optional; |
| |
| namespace detail { |
| |
| // C++11 emulation: |
| |
| struct nulltype{}; |
| |
| template< typename Head, typename Tail > |
| struct typelist |
| { |
| typedef Head head; |
| typedef Tail tail; |
| }; |
| |
| #if optional_CONFIG_MAX_ALIGN_HACK |
| |
| // Max align, use most restricted type for alignment: |
| |
| #define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ ) |
| #define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line ) |
| #define optional_UNIQUE3( name, line ) name ## line |
| |
| #define optional_ALIGN_TYPE( type ) \ |
| type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st ) |
| |
| template< typename T > |
| struct struct_t { T _; }; |
| |
| union max_align_t |
| { |
| optional_ALIGN_TYPE( char ); |
| optional_ALIGN_TYPE( short int ); |
| optional_ALIGN_TYPE( int ); |
| optional_ALIGN_TYPE( long int ); |
| optional_ALIGN_TYPE( float ); |
| optional_ALIGN_TYPE( double ); |
| optional_ALIGN_TYPE( long double ); |
| optional_ALIGN_TYPE( char * ); |
| optional_ALIGN_TYPE( short int * ); |
| optional_ALIGN_TYPE( int * ); |
| optional_ALIGN_TYPE( long int * ); |
| optional_ALIGN_TYPE( float * ); |
| optional_ALIGN_TYPE( double * ); |
| optional_ALIGN_TYPE( long double * ); |
| optional_ALIGN_TYPE( void * ); |
| |
| #ifdef HAVE_LONG_LONG |
| optional_ALIGN_TYPE( long long ); |
| #endif |
| |
| struct Unknown; |
| |
| Unknown ( * optional_UNIQUE(_) )( Unknown ); |
| Unknown * Unknown::* optional_UNIQUE(_); |
| Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown ); |
| |
| struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_); |
| struct_t< Unknown * Unknown::* > optional_UNIQUE(_); |
| struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_); |
| }; |
| |
| #undef optional_UNIQUE |
| #undef optional_UNIQUE2 |
| #undef optional_UNIQUE3 |
| |
| #undef optional_ALIGN_TYPE |
| |
| #elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK |
| |
| // Use user-specified type for alignment: |
| |
| #define optional_ALIGN_AS( unused ) \ |
| optional_CONFIG_ALIGN_AS |
| |
| #else // optional_CONFIG_MAX_ALIGN_HACK |
| |
| // Determine POD type to use for alignment: |
| |
| #define optional_ALIGN_AS( to_align ) \ |
| typename type_of_size< alignment_types, alignment_of< to_align >::value >::type |
| |
| template< typename T > |
| struct alignment_of; |
| |
| template< typename T > |
| struct alignment_of_hack |
| { |
| char c; |
| T t; |
| alignment_of_hack(); |
| }; |
| |
| template< size_t A, size_t S > |
| struct alignment_logic |
| { |
| enum { value = A < S ? A : S }; |
| }; |
| |
| template< typename T > |
| struct alignment_of |
| { |
| enum { value = alignment_logic< |
| sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value }; |
| }; |
| |
| template< typename List, size_t N > |
| struct type_of_size |
| { |
| typedef typename conditional< |
| N == sizeof( typename List::head ), |
| typename List::head, |
| typename type_of_size<typename List::tail, N >::type >::type type; |
| }; |
| |
| template< size_t N > |
| struct type_of_size< nulltype, N > |
| { |
| typedef optional_CONFIG_ALIGN_AS_FALLBACK type; |
| }; |
| |
| template< typename T> |
| struct struct_t { T _; }; |
| |
| #define optional_ALIGN_TYPE( type ) \ |
| typelist< type , typelist< struct_t< type > |
| |
| struct Unknown; |
| |
| typedef |
| optional_ALIGN_TYPE( char ), |
| optional_ALIGN_TYPE( short ), |
| optional_ALIGN_TYPE( int ), |
| optional_ALIGN_TYPE( long ), |
| optional_ALIGN_TYPE( float ), |
| optional_ALIGN_TYPE( double ), |
| optional_ALIGN_TYPE( long double ), |
| |
| optional_ALIGN_TYPE( char *), |
| optional_ALIGN_TYPE( short * ), |
| optional_ALIGN_TYPE( int * ), |
| optional_ALIGN_TYPE( long * ), |
| optional_ALIGN_TYPE( float * ), |
| optional_ALIGN_TYPE( double * ), |
| optional_ALIGN_TYPE( long double * ), |
| |
| optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ), |
| optional_ALIGN_TYPE( Unknown * Unknown::* ), |
| optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ), |
| |
| nulltype |
| > > > > > > > > > > > > > > |
| > > > > > > > > > > > > > > |
| > > > > > > |
| alignment_types; |
| |
| #undef optional_ALIGN_TYPE |
| |
| #endif // optional_CONFIG_MAX_ALIGN_HACK |
| |
| /// C++03 constructed union to hold value. |
| |
| template< typename T > |
| union storage_t |
| { |
| //private: |
| // template< typename > friend class optional; |
| |
| typedef T value_type; |
| |
| storage_t() {} |
| |
| storage_t( value_type const & v ) |
| { |
| construct_value( v ); |
| } |
| |
| void construct_value( value_type const & v ) |
| { |
| ::new( value_ptr() ) value_type( v ); |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| storage_t( value_type && v ) |
| { |
| construct_value( std::move( v ) ); |
| } |
| |
| void construct_value( value_type && v ) |
| { |
| ::new( value_ptr() ) value_type( std::move( v ) ); |
| } |
| |
| template< class... Args > |
| void emplace( Args&&... args ) |
| { |
| ::new( value_ptr() ) value_type( std::forward<Args>(args)... ); |
| } |
| |
| template< class U, class... Args > |
| void emplace( std::initializer_list<U> il, Args&&... args ) |
| { |
| ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... ); |
| } |
| |
| #endif |
| |
| void destruct_value() |
| { |
| value_ptr()->~T(); |
| } |
| |
| value_type const * value_ptr() const |
| { |
| return as<value_type>(); |
| } |
| |
| value_type * value_ptr() |
| { |
| return as<value_type>(); |
| } |
| |
| value_type const & value() const optional_ref_qual |
| { |
| return * value_ptr(); |
| } |
| |
| value_type & value() optional_ref_qual |
| { |
| return * value_ptr(); |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| value_type const && value() const optional_refref_qual |
| { |
| return std::move( value() ); |
| } |
| |
| value_type && value() optional_refref_qual |
| { |
| return std::move( value() ); |
| } |
| |
| #endif |
| |
| #if optional_CPP11_OR_GREATER |
| |
| using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type; |
| aligned_storage_t data; |
| |
| #elif optional_CONFIG_MAX_ALIGN_HACK |
| |
| typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t; |
| |
| max_align_t hack; |
| aligned_storage_t data; |
| |
| #else |
| typedef optional_ALIGN_AS(value_type) align_as_type; |
| |
| typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t; |
| aligned_storage_t data; |
| |
| # undef optional_ALIGN_AS |
| |
| #endif // optional_CONFIG_MAX_ALIGN_HACK |
| |
| void * ptr() optional_noexcept |
| { |
| return &data; |
| } |
| |
| void const * ptr() const optional_noexcept |
| { |
| return &data; |
| } |
| |
| template <typename U> |
| U * as() |
| { |
| return reinterpret_cast<U*>( ptr() ); |
| } |
| |
| template <typename U> |
| U const * as() const |
| { |
| return reinterpret_cast<U const *>( ptr() ); |
| } |
| }; |
| |
| } // namespace detail |
| |
| /// disengaged state tag |
| |
| struct nullopt_t |
| { |
| struct init{}; |
| optional_constexpr nullopt_t( init ) {} |
| }; |
| |
| #if optional_HAVE( CONSTEXPR_11 ) |
| constexpr nullopt_t nullopt{ nullopt_t::init{} }; |
| #else |
| // extra parenthesis to prevent the most vexing parse: |
| const nullopt_t nullopt(( nullopt_t::init() )); |
| #endif |
| |
| /// optional access error |
| |
| class bad_optional_access : public std::logic_error |
| { |
| public: |
| explicit bad_optional_access() |
| : logic_error( "bad optional access" ) {} |
| }; |
| |
| /// optional |
| |
| template< typename T> |
| class optional |
| { |
| private: |
| template< typename > friend class optional; |
| |
| typedef void (optional::*safe_bool)() const; |
| |
| public: |
| typedef T value_type; |
| |
| // x.x.3.1, constructors |
| |
| // 1a - default construct |
| optional_constexpr optional() optional_noexcept |
| : has_value_( false ) |
| , contained() |
| {} |
| |
| // 1b - construct explicitly empty |
| optional_constexpr optional( nullopt_t ) optional_noexcept |
| : has_value_( false ) |
| , contained() |
| {} |
| |
| // 2 - copy-construct |
| optional_constexpr14 optional( optional const & other |
| #if optional_CPP11_OR_GREATER |
| optional_REQUIRES_A( |
| true || std::is_copy_constructible<T>::value |
| ) |
| #endif |
| ) |
| : has_value_( other.has_value() ) |
| { |
| if ( other.has_value() ) |
| contained.construct_value( other.contained.value() ); |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| // 3 (C++11) - move-construct from optional |
| optional_constexpr14 optional( optional && other |
| optional_REQUIRES_A( |
| true || std::is_move_constructible<T>::value |
| ) |
| ) noexcept( std::is_nothrow_move_constructible<T>::value ) |
| : has_value_( other.has_value() ) |
| { |
| if ( other.has_value() ) |
| contained.construct_value( std::move( other.contained.value() ) ); |
| } |
| |
| // 4 (C++11) - explicit converting copy-construct from optional |
| template< typename U > |
| explicit optional( optional<U> const & other |
| optional_REQUIRES_A( |
| std::is_constructible<T, U const &>::value |
| && !std::is_constructible<T, optional<U> & >::value |
| && !std::is_constructible<T, optional<U> && >::value |
| && !std::is_constructible<T, optional<U> const & >::value |
| && !std::is_constructible<T, optional<U> const && >::value |
| && !std::is_convertible< optional<U> & , T>::value |
| && !std::is_convertible< optional<U> && , T>::value |
| && !std::is_convertible< optional<U> const & , T>::value |
| && !std::is_convertible< optional<U> const &&, T>::value |
| && !std::is_convertible< U const & , T>::value /*=> explicit */ |
| ) |
| ) |
| : has_value_( other.has_value() ) |
| { |
| if ( other.has_value() ) |
| contained.construct_value( other.contained.value() ); |
| } |
| #endif // optional_CPP11_OR_GREATER |
| |
| // 4 (C++98 and later) - non-explicit converting copy-construct from optional |
| template< typename U > |
| optional( optional<U> const & other |
| #if optional_CPP11_OR_GREATER |
| optional_REQUIRES_A( |
| std::is_constructible<T, U const &>::value |
| && !std::is_constructible<T, optional<U> & >::value |
| && !std::is_constructible<T, optional<U> && >::value |
| && !std::is_constructible<T, optional<U> const & >::value |
| && !std::is_constructible<T, optional<U> const && >::value |
| && !std::is_convertible< optional<U> & , T>::value |
| && !std::is_convertible< optional<U> && , T>::value |
| && !std::is_convertible< optional<U> const & , T>::value |
| && !std::is_convertible< optional<U> const &&, T>::value |
| && std::is_convertible< U const & , T>::value /*=> non-explicit */ |
| ) |
| #endif // optional_CPP11_OR_GREATER |
| ) |
| : has_value_( other.has_value() ) |
| { |
| if ( other.has_value() ) |
| contained.construct_value( other.contained.value() ); |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| // 5a (C++11) - explicit converting move-construct from optional |
| template< typename U > |
| optional( optional<U> && other |
| optional_REQUIRES_A( |
| std::is_constructible<T, U const &>::value |
| && !std::is_constructible<T, optional<U> & >::value |
| && !std::is_constructible<T, optional<U> && >::value |
| && !std::is_constructible<T, optional<U> const & >::value |
| && !std::is_constructible<T, optional<U> const && >::value |
| && !std::is_convertible< optional<U> & , T>::value |
| && !std::is_convertible< optional<U> && , T>::value |
| && !std::is_convertible< optional<U> const & , T>::value |
| && !std::is_convertible< optional<U> const &&, T>::value |
| && !std::is_convertible< U &&, T>::value /*=> explicit */ |
| ) |
| ) |
| : has_value_( other.has_value() ) |
| { |
| if ( other.has_value() ) |
| contained.construct_value( std::move( other.contained.value() ) ); |
| } |
| |
| // 5a (C++11) - non-explicit converting move-construct from optional |
| template< typename U > |
| optional( optional<U> && other |
| optional_REQUIRES_A( |
| std::is_constructible<T, U const &>::value |
| && !std::is_constructible<T, optional<U> & >::value |
| && !std::is_constructible<T, optional<U> && >::value |
| && !std::is_constructible<T, optional<U> const & >::value |
| && !std::is_constructible<T, optional<U> const && >::value |
| && !std::is_convertible< optional<U> & , T>::value |
| && !std::is_convertible< optional<U> && , T>::value |
| && !std::is_convertible< optional<U> const & , T>::value |
| && !std::is_convertible< optional<U> const &&, T>::value |
| && std::is_convertible< U &&, T>::value /*=> non-explicit */ |
| ) |
| ) |
| : has_value_( other.has_value() ) |
| { |
| if ( other.has_value() ) |
| contained.construct_value( std::move( other.contained.value() ) ); |
| } |
| |
| // 6 (C++11) - in-place construct |
| template< typename... Args |
| optional_REQUIRES_T( |
| std::is_constructible<T, Args&&...>::value |
| ) |
| > |
| optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args ) |
| : has_value_( true ) |
| , contained( T( std::forward<Args>(args)...) ) |
| {} |
| |
| // 7 (C++11) - in-place construct, initializer-list |
| template< typename U, typename... Args |
| optional_REQUIRES_T( |
| std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value |
| ) |
| > |
| optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args ) |
| : has_value_( true ) |
| , contained( T( il, std::forward<Args>(args)...) ) |
| {} |
| |
| // 8a (C++11) - explicit move construct from value |
| template< typename U = value_type > |
| optional_constexpr explicit optional( U && value |
| optional_REQUIRES_A( |
| std::is_constructible<T, U&&>::value |
| && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value |
| && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value |
| && !std::is_convertible<U&&, T>::value /*=> explicit */ |
| ) |
| ) |
| : has_value_( true ) |
| , contained( std::forward<U>( value ) ) |
| {} |
| |
| // 8a (C++11) - non-explicit move construct from value |
| template< typename U = value_type > |
| optional_constexpr optional( U && value |
| optional_REQUIRES_A( |
| std::is_constructible<T, U&&>::value |
| && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value |
| && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value |
| && std::is_convertible<U&&, T>::value /*=> non-explicit */ |
| ) |
| ) |
| : has_value_( true ) |
| , contained( std::forward<U>( value ) ) |
| {} |
| |
| #else // optional_CPP11_OR_GREATER |
| |
| // 8 (C++98) |
| optional( value_type const & value ) |
| : has_value_( true ) |
| , contained( value ) |
| {} |
| |
| #endif // optional_CPP11_OR_GREATER |
| |
| // x.x.3.2, destructor |
| |
| ~optional() |
| { |
| if ( has_value() ) |
| contained.destruct_value(); |
| } |
| |
| // x.x.3.3, assignment |
| |
| // 1 (C++98and later) - assign explicitly empty |
| optional & operator=( nullopt_t ) optional_noexcept |
| { |
| reset(); |
| return *this; |
| } |
| |
| // 2 (C++98and later) - copy-assign from optional |
| #if optional_CPP11_OR_GREATER |
| optional_REQUIRES_R( |
| optional &, |
| true |
| // std::is_copy_constructible<T>::value |
| // && std::is_copy_assignable<T>::value |
| ) |
| operator=( optional const & other ) |
| noexcept( |
| std::is_nothrow_move_assignable<T>::value |
| && std::is_nothrow_move_constructible<T>::value |
| ) |
| #else |
| optional & operator=( optional const & other ) |
| #endif |
| { |
| if ( has_value() == true && other.has_value() == false ) reset(); |
| else if ( has_value() == false && other.has_value() == true ) initialize( *other ); |
| else if ( has_value() == true && other.has_value() == true ) contained.value() = *other; |
| return *this; |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| // 3 (C++11) - move-assign from optional |
| optional_REQUIRES_R( |
| optional &, |
| true |
| // std::is_move_constructible<T>::value |
| // && std::is_move_assignable<T>::value |
| ) |
| operator=( optional && other ) noexcept |
| { |
| if ( has_value() == true && other.has_value() == false ) reset(); |
| else if ( has_value() == false && other.has_value() == true ) initialize( std::move( *other ) ); |
| else if ( has_value() == true && other.has_value() == true ) contained.value() = std::move( *other ); |
| return *this; |
| } |
| |
| // 4 (C++11) - move-assign from value |
| template< typename U = T > |
| optional_REQUIRES_R( |
| optional &, |
| std::is_constructible<T , U>::value |
| && std::is_assignable<T&, U>::value |
| && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value |
| && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value |
| // && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value) |
| ) |
| operator=( U && value ) |
| { |
| if ( has_value() ) contained.value() = std::forward<U>( value ); |
| else initialize( T( std::forward<U>( value ) ) ); |
| return *this; |
| } |
| |
| #else // optional_CPP11_OR_GREATER |
| |
| // 4 (C++98) - copy-assign from value |
| template< typename U /*= T*/ > |
| optional & operator=( U const & value ) |
| { |
| if ( has_value() ) contained.value() = value; |
| else initialize( T( value ) ); |
| return *this; |
| } |
| |
| #endif // optional_CPP11_OR_GREATER |
| |
| // 5 (C++98 and later) - converting copy-assign from optional |
| template< typename U > |
| #if optional_CPP11_OR_GREATER |
| optional_REQUIRES_R( |
| optional&, |
| std::is_constructible< T , U const &>::value |
| && std::is_assignable< T&, U const &>::value |
| && !std::is_constructible<T, optional<U> & >::value |
| && !std::is_constructible<T, optional<U> && >::value |
| && !std::is_constructible<T, optional<U> const & >::value |
| && !std::is_constructible<T, optional<U> const && >::value |
| && !std::is_convertible< optional<U> & , T>::value |
| && !std::is_convertible< optional<U> && , T>::value |
| && !std::is_convertible< optional<U> const & , T>::value |
| && !std::is_convertible< optional<U> const &&, T>::value |
| && !std::is_assignable< T&, optional<U> & >::value |
| && !std::is_assignable< T&, optional<U> && >::value |
| && !std::is_assignable< T&, optional<U> const & >::value |
| && !std::is_assignable< T&, optional<U> const && >::value |
| ) |
| #else |
| optional& |
| #endif // optional_CPP11_OR_GREATER |
| operator=( optional<U> const & other ) |
| { |
| return *this = optional( other ); |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| // 6 (C++11) - converting move-assign from optional |
| template< typename U > |
| optional_REQUIRES_R( |
| optional&, |
| std::is_constructible< T , U>::value |
| && std::is_assignable< T&, U>::value |
| && !std::is_constructible<T, optional<U> & >::value |
| && !std::is_constructible<T, optional<U> && >::value |
| && !std::is_constructible<T, optional<U> const & >::value |
| && !std::is_constructible<T, optional<U> const && >::value |
| && !std::is_convertible< optional<U> & , T>::value |
| && !std::is_convertible< optional<U> && , T>::value |
| && !std::is_convertible< optional<U> const & , T>::value |
| && !std::is_convertible< optional<U> const &&, T>::value |
| && !std::is_assignable< T&, optional<U> & >::value |
| && !std::is_assignable< T&, optional<U> && >::value |
| && !std::is_assignable< T&, optional<U> const & >::value |
| && !std::is_assignable< T&, optional<U> const && >::value |
| ) |
| operator=( optional<U> && other ) |
| { |
| return *this = optional( std::move( other ) ); |
| } |
| |
| // 7 (C++11) - emplace |
| template< typename... Args |
| optional_REQUIRES_T( |
| std::is_constructible<T, Args&&...>::value |
| ) |
| > |
| T& emplace( Args&&... args ) |
| { |
| *this = nullopt; |
| contained.emplace( std::forward<Args>(args)... ); |
| has_value_ = true; |
| return contained.value(); |
| } |
| |
| // 8 (C++11) - emplace, initializer-list |
| template< typename U, typename... Args |
| optional_REQUIRES_T( |
| std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value |
| ) |
| > |
| T& emplace( std::initializer_list<U> il, Args&&... args ) |
| { |
| *this = nullopt; |
| contained.emplace( il, std::forward<Args>(args)... ); |
| has_value_ = true; |
| return contained.value(); |
| } |
| |
| #endif // optional_CPP11_OR_GREATER |
| |
| // x.x.3.4, swap |
| |
| void swap( optional & other ) |
| #if optional_CPP11_OR_GREATER |
| noexcept( |
| std::is_nothrow_move_constructible<T>::value |
| && noexcept( std::swap( std::declval<T&>(), std::declval<T&>() ) ) |
| ) |
| #endif |
| { |
| using std::swap; |
| if ( has_value() == true && other.has_value() == true ) { swap( **this, *other ); } |
| else if ( has_value() == false && other.has_value() == true ) { initialize( *other ); other.reset(); } |
| else if ( has_value() == true && other.has_value() == false ) { other.initialize( **this ); reset(); } |
| } |
| |
| // x.x.3.5, observers |
| |
| optional_constexpr value_type const * operator ->() const |
| { |
| return assert( has_value() ), |
| contained.value_ptr(); |
| } |
| |
| optional_constexpr14 value_type * operator ->() |
| { |
| return assert( has_value() ), |
| contained.value_ptr(); |
| } |
| |
| optional_constexpr value_type const & operator *() const optional_ref_qual |
| { |
| return assert( has_value() ), |
| contained.value(); |
| } |
| |
| optional_constexpr14 value_type & operator *() optional_ref_qual |
| { |
| return assert( has_value() ), |
| contained.value(); |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| optional_constexpr value_type const && operator *() const optional_refref_qual |
| { |
| return std::move( **this ); |
| } |
| |
| optional_constexpr14 value_type && operator *() optional_refref_qual |
| { |
| return std::move( **this ); |
| } |
| |
| #endif |
| |
| #if optional_CPP11_OR_GREATER |
| optional_constexpr explicit operator bool() const optional_noexcept |
| { |
| return has_value(); |
| } |
| #else |
| optional_constexpr operator safe_bool() const optional_noexcept |
| { |
| return has_value() ? &optional::this_type_does_not_support_comparisons : 0; |
| } |
| #endif |
| |
| optional_constexpr bool has_value() const optional_noexcept |
| { |
| return has_value_; |
| } |
| |
| optional_constexpr14 value_type const & value() const optional_ref_qual |
| { |
| if ( ! has_value() ) |
| throw bad_optional_access(); |
| |
| return contained.value(); |
| } |
| |
| optional_constexpr14 value_type & value() optional_ref_qual |
| { |
| if ( ! has_value() ) |
| throw bad_optional_access(); |
| |
| return contained.value(); |
| } |
| |
| #if optional_HAVE( REF_QUALIFIER ) |
| |
| optional_constexpr14 value_type const && value() const optional_refref_qual |
| { |
| return std::move( value() ); |
| } |
| |
| optional_constexpr14 value_type && value() optional_refref_qual |
| { |
| return std::move( value() ); |
| } |
| |
| #endif |
| |
| #if optional_CPP11_OR_GREATER |
| |
| template< typename U > |
| optional_constexpr value_type value_or( U && v ) const optional_ref_qual |
| { |
| return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) ); |
| } |
| |
| template< typename U > |
| optional_constexpr value_type value_or( U && v ) const optional_refref_qual |
| { |
| return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) ); |
| } |
| |
| #else |
| |
| template< typename U > |
| optional_constexpr value_type value_or( U const & v ) const |
| { |
| return has_value() ? contained.value() : static_cast<value_type>( v ); |
| } |
| |
| #endif // optional_CPP11_OR_GREATER |
| |
| // x.x.3.6, modifiers |
| |
| void reset() optional_noexcept |
| { |
| if ( has_value() ) |
| contained.destruct_value(); |
| |
| has_value_ = false; |
| } |
| |
| private: |
| void this_type_does_not_support_comparisons() const {} |
| |
| template< typename V > |
| void initialize( V const & value ) |
| { |
| assert( ! has_value() ); |
| contained.construct_value( value ); |
| has_value_ = true; |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| template< typename V > |
| void initialize( V && value ) |
| { |
| assert( ! has_value() ); |
| contained.construct_value( std::move( value ) ); |
| has_value_ = true; |
| } |
| |
| #endif |
| |
| private: |
| bool has_value_; |
| detail::storage_t< value_type > contained; |
| |
| }; |
| |
| // Relational operators |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y ) |
| { |
| return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y ) |
| { |
| return !(x == y); |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y ) |
| { |
| return (!y) ? false : (!x) ? true : *x < *y; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y ) |
| { |
| return (y < x); |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y ) |
| { |
| return !(y < x); |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y ) |
| { |
| return !(x < y); |
| } |
| |
| // Comparison with nullopt |
| |
| template< typename T > |
| inline optional_constexpr bool operator==( optional<T> const & x, nullopt_t ) optional_noexcept |
| { |
| return (!x); |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator==( nullopt_t, optional<T> const & x ) optional_noexcept |
| { |
| return (!x); |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator!=( optional<T> const & x, nullopt_t ) optional_noexcept |
| { |
| return bool(x); |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator!=( nullopt_t, optional<T> const & x ) optional_noexcept |
| { |
| return bool(x); |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator<( optional<T> const &, nullopt_t ) optional_noexcept |
| { |
| return false; |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator<( nullopt_t, optional<T> const & x ) optional_noexcept |
| { |
| return bool(x); |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator<=( optional<T> const & x, nullopt_t ) optional_noexcept |
| { |
| return (!x); |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator<=( nullopt_t, optional<T> const & ) optional_noexcept |
| { |
| return true; |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator>( optional<T> const & x, nullopt_t ) optional_noexcept |
| { |
| return bool(x); |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator>( nullopt_t, optional<T> const & ) optional_noexcept |
| { |
| return false; |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator>=( optional<T> const &, nullopt_t ) optional_noexcept |
| { |
| return true; |
| } |
| |
| template< typename T > |
| inline optional_constexpr bool operator>=( nullopt_t, optional<T> const & x ) optional_noexcept |
| { |
| return (!x); |
| } |
| |
| // Comparison with T |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator==( optional<T> const & x, U const & v ) |
| { |
| return bool(x) ? *x == v : false; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator==( U const & v, optional<T> const & x ) |
| { |
| return bool(x) ? v == *x : false; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator!=( optional<T> const & x, U const & v ) |
| { |
| return bool(x) ? *x != v : true; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator!=( U const & v, optional<T> const & x ) |
| { |
| return bool(x) ? v != *x : true; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator<( optional<T> const & x, U const & v ) |
| { |
| return bool(x) ? *x < v : true; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator<( U const & v, optional<T> const & x ) |
| { |
| return bool(x) ? v < *x : false; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator<=( optional<T> const & x, U const & v ) |
| { |
| return bool(x) ? *x <= v : true; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator<=( U const & v, optional<T> const & x ) |
| { |
| return bool(x) ? v <= *x : false; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator>( optional<T> const & x, U const & v ) |
| { |
| return bool(x) ? *x > v : false; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator>( U const & v, optional<T> const & x ) |
| { |
| return bool(x) ? v > *x : true; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator>=( optional<T> const & x, U const & v ) |
| { |
| return bool(x) ? *x >= v : false; |
| } |
| |
| template< typename T, typename U > |
| inline optional_constexpr bool operator>=( U const & v, optional<T> const & x ) |
| { |
| return bool(x) ? v >= *x : true; |
| } |
| |
| // Specialized algorithms |
| |
| template< typename T > |
| void swap( optional<T> & x, optional<T> & y ) |
| #if optional_CPP11_OR_GREATER |
| noexcept( noexcept( x.swap(y) ) ) |
| #endif |
| { |
| x.swap( y ); |
| } |
| |
| #if optional_CPP11_OR_GREATER |
| |
| template< typename T > |
| optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value ) |
| { |
| return optional< typename std::decay<T>::type >( std::forward<T>( value ) ); |
| } |
| |
| template< typename T, typename...Args > |
| optional_constexpr optional<T> make_optional( Args&&... args ) |
| { |
| return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...); |
| } |
| |
| template< typename T, typename U, typename... Args > |
| optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args ) |
| { |
| return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...); |
| } |
| |
| #else |
| |
| template< typename T > |
| optional<T> make_optional( T const & value ) |
| { |
| return optional<T>( value ); |
| } |
| |
| #endif // optional_CPP11_OR_GREATER |
| |
| } // namespace optional_lite |
| |
| using namespace optional_lite; |
| |
| } // namespace nonstd |
| |
| #if optional_CPP11_OR_GREATER |
| |
| // specialize the std::hash algorithm: |
| |
| namespace std { |
| |
| template< class T > |
| struct hash< nonstd::optional<T> > |
| { |
| public: |
| std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept |
| { |
| return bool( v ) ? hash<T>()( *v ) : 0; |
| } |
| }; |
| |
| } //namespace std |
| |
| #endif // optional_CPP11_OR_GREATER |
| |
| #if defined (__clang__) |
| # pragma clang diagnostic pop |
| #elif defined (__GNUC__) |
| # pragma GCC diagnostic pop |
| #endif |
| |
| #endif // optional_USES_STD_OPTIONAL |
| |
| #endif // NONSTD_OPTIONAL_LITE_HPP |