[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/martinmoene/optional-lite/master/include/nonstd/optional.hpp [Back]  [Original]

//
// Copyright (c) 2014-2021 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  6
#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

// tweak header support:

#ifdef __has_include
# if __has_include()
#  include 
# endif
#define optional_HAVE_TWEAK_HEADER  1
#else
#define optional_HAVE_TWEAK_HEADER  0
//# pragma message("optional.hpp: Note: Tweak header not supported.")
#endif

// optional selection and configuration:

#if !defined( optional_CONFIG_SELECT_OPTIONAL )
# define optional_CONFIG_SELECT_OPTIONAL  ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
#endif

// Control presence of extensions:

#ifndef optional_CONFIG_NO_EXTENSIONS
#define optional_CONFIG_NO_EXTENSIONS  0
#endif

// Control marking class bad_optional_access and several methods with [[nodiscard]]]:

#if !defined(optional_CONFIG_NO_NODISCARD)
# define optional_CONFIG_NO_NODISCARD  0
#else
# define optional_CONFIG_NO_NODISCARD  1
#endif

// Control presence of exception handling (try and auto discover):

#ifndef optional_CONFIG_NO_EXCEPTIONS
# if defined(_MSC_VER)
# include      // for _HAS_EXCEPTIONS
# endif
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS))
#  define optional_CONFIG_NO_EXCEPTIONS  0
# else
#  define optional_CONFIG_NO_EXCEPTIONS  1
# endif
#endif

// C++ language version detection (C++23 is speculative):
// Note: VC14.0/1900 (VS2015) lacks too much from C++14.

#ifndef   optional_CPLUSPLUS
# if defined(_MSVC_LANG ) && !defined(__clang__)
#  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_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 >= 202002L )
#define optional_CPP23_OR_GREATER  ( optional_CPLUSPLUS >= 202300L )

// 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(  )
#  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) )

//
// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
//

#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
#define nonstd_lite_HAVE_IN_PLACE_TYPES  1

// C++17 std::in_place in :

#if optional_CPP17_OR_GREATER

#include 

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
#define nonstd_lite_in_place_index_t(K)  std::in_place_index_t

#define nonstd_lite_in_place(      T)    std::in_place_t{}
#define nonstd_lite_in_place_type( T)    std::in_place_type_t{}
#define nonstd_lite_in_place_index(K)    std::in_place_index_t{}

} // namespace nonstd

#else // optional_CPP17_OR_GREATER

#include 

namespace nonstd {
namespace detail {

template< class T >
struct in_place_type_tag {};

template< std::size_t K >
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 /*unused*/ = detail::in_place_type_tag() )
{
    return in_place_t();
}

template< std::size_t K >
inline in_place_t in_place( detail::in_place_index_tag /*unused*/ = detail::in_place_index_tag() )
{
    return in_place_t();
}

template< class T >
inline in_place_t in_place_type( detail::in_place_type_tag /*unused*/ = detail::in_place_type_tag() )
{
    return in_place_t();
}

template< std::size_t K >
inline in_place_t in_place_index( detail::in_place_index_tag /*unused*/ = detail::in_place_index_tag() )
{
    return in_place_t();
}

// mimic templated typedef:

#define nonstd_lite_in_place_t(      T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag  )
#define nonstd_lite_in_place_type_t( T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag  )
#define nonstd_lite_in_place_index_t(K)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag )

#define nonstd_lite_in_place(      T)    nonstd::in_place_type
#define nonstd_lite_in_place_type( T)    nonstd::in_place_type
#define nonstd_lite_in_place_index(K)    nonstd::in_place_index

} // namespace nonstd

#endif // optional_CPP17_OR_GREATER
#endif // nonstd_lite_HAVE_IN_PLACE_TYPES

//
// Using std::optional:
//

#if optional_USES_STD_OPTIONAL

#include 

namespace nonstd {

    using std::optional;
    using std::bad_optional_access;
    using std::hash;

    using std::nullopt;
    using std::nullopt_t;

    using std::operator==;
    using std::operator!=;
    using std::operator=;
    using std::make_optional;
    using std::swap;
}

#else // optional_USES_STD_OPTIONAL

#include 
#include 

// 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"
#elif defined(_MSC_VER )
# pragma warning( push )
#endif

// half-open range [lo..hi):
#define optional_BETWEEN( v, lo, hi ) ( (lo) = 1910  optional_COMPILER_MSVC_VERSION == 141  (Visual Studio 2017)
// MSVC++ 14.2  _MSC_VER >= 1920  optional_COMPILER_MSVC_VERSION == 142  (Visual Studio 2019)

#if defined(_MSC_VER ) && !defined(__clang__)
# define optional_COMPILER_MSVC_VER      (_MSC_VER )
# define optional_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
#else
# define optional_COMPILER_MSVC_VER      0
# 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( disable: 4345 )   // initialization behavior changed
#endif

#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
# 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 )

#ifdef _HAS_CPP0X
# define optional_HAS_CPP0X  _HAS_CPP0X
#else
# define optional_HAS_CPP0X  0
#endif

// Unless defined otherwise below, consider VC14 as C++11 for optional-lite:

#if optional_COMPILER_MSVC_VER >= 1900
# undef  optional_CPP11_OR_GREATER
# define optional_CPP11_OR_GREATER  1
#endif

#define optional_CPP11_90   (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
#define optional_CPP11_100  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
#define optional_CPP11_110  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
#define optional_CPP11_120  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
#define optional_CPP11_140  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
#define optional_CPP11_141  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)

#define optional_CPP14_000  (optional_CPP14_OR_GREATER)
#define optional_CPP17_000  (optional_CPP17_OR_GREATER)

// clang >= 2.9, gcc >= 4.9, msvc >= vc14.0/1900 (vs15):
#define optional_CPP11_140_C290_G490    ((optional_CPP11_OR_GREATER_ && (optional_COMPILER_CLANG_VERSION >= 290 || optional_COMPILER_GNUC_VERSION >= 490)) || (optional_COMPILER_MSVC_VER >= 1900))

// clang >= 3.5, msvc >= vc11 (vs12):
#define optional_CPP11_110_C350         ( optional_CPP11_110 && !optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) )

// clang >= 3.5, gcc >= 5.0, msvc >= vc11 (vs12):
#define optional_CPP11_110_C350_G500 \
    (  optional_CPP11_110 && \
    !( optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) \
    || optional_BETWEEN( optional_COMPILER_GNUC_VERSION , 1, 500 ) ) )

// Presence of C++11 language features:

#define optional_HAVE_CONSTEXPR_11      optional_CPP11_140
#define optional_HAVE_IS_DEFAULT        optional_CPP11_140
#define optional_HAVE_NOEXCEPT          optional_CPP11_140
#define optional_HAVE_NULLPTR           optional_CPP11_100
#define optional_HAVE_REF_QUALIFIER     optional_CPP11_140_C290_G490
#define optional_HAVE_STATIC_ASSERT     optional_CPP11_110
#define optional_HAVE_INITIALIZER_LIST  optional_CPP11_140

// Presence of C++14 language features:

#define optional_HAVE_CONSTEXPR_14      optional_CPP14_000

// Presence of C++17 language features:

#define optional_HAVE_NODISCARD         optional_CPP17_000

// Presence of C++ library features:

#define optional_HAVE_CONDITIONAL       optional_CPP11_120
#define optional_HAVE_REMOVE_CV         optional_CPP11_120
#define optional_HAVE_TYPE_TRAITS       optional_CPP11_90

#define optional_HAVE_TR1_TYPE_TRAITS   (!! optional_COMPILER_GNUC_VERSION )
#define optional_HAVE_TR1_ADD_POINTER   (!! optional_COMPILER_GNUC_VERSION )

#define optional_HAVE_IS_ASSIGNABLE                     optional_CPP11_110_C350
#define optional_HAVE_IS_MOVE_CONSTRUCTIBLE             optional_CPP11_110_C350
#define optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE        optional_CPP11_110_C350
#define optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE     optional_CPP11_110_C350
#define optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE   optional_CPP11_110_C350_G500
#define optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE   optional_CPP11_110_C350_G500

// C++ feature usage:

#if optional_HAVE( CONSTEXPR_11 )
# define optional_constexpr  constexpr
#else
# define optional_constexpr  /*constexpr*/
#endif

#if optional_HAVE( IS_DEFAULT )
# define optional_is_default  = default;
#else
# define optional_is_default  {}
#endif

#if optional_HAVE( CONSTEXPR_14 )
# define optional_constexpr14  constexpr
#else
# define optional_constexpr14  /*constexpr*/
#endif

#if optional_HAVE( NODISCARD ) && !optional_CONFIG_NO_NODISCARD
# define optional_nodiscard  [[nodiscard]]
#else
# define optional_nodiscard  /*[[nodiscard]]*/
#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 )
// NOLINTNEXTLINE( bugprone-macro-parentheses )
# define optional_ref_qual  &
# define optional_refref_qual  &&
#else
# define optional_ref_qual  /*&*/
# define optional_refref_qual  /*&&*/
#endif

#if optional_HAVE( STATIC_ASSERT )
# define optional_static_assert(expr, text)    static_assert(expr, text);
#else
# define optional_static_assert(expr, text)  /*static_assert(expr, text);*/
#endif

// additional includes:

#if optional_CONFIG_NO_EXCEPTIONS
// already included: 
#else
# include 
#endif

#if optional_CPP11_OR_GREATER
# include 
#endif

#if optional_HAVE( INITIALIZER_LIST )
# include 
#endif

#if optional_HAVE( TYPE_TRAITS )
# include 
#elif optional_HAVE( TR1_TYPE_TRAITS )
# include 
#endif

// Method enabling

#if optional_CPP11_OR_GREATER

#define optional_REQUIRES_0(...) \
    template< bool B = (__VA_ARGS__), typename std::enable_if::type = 0 >

#define optional_REQUIRES_T(...) \
    , typename std::enable_if< (__VA_ARGS__), int >::type = 0

#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 = nullptr

#endif

//
// optional:
//

namespace nonstd { namespace optional_lite {

namespace std11 {

template< class T, T v > struct integral_constant { enum { value = v }; };
template< bool B       > struct bool_constant : integral_constant{};

typedef bool_constant< true  > true_type;
typedef bool_constant< false > false_type;

#if optional_CPP11_OR_GREATER
    using std::move;
#else
    template< typename T > T & move( T & t ) { return t; }
#endif

#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 { typedef F type; };
#endif // optional_HAVE_CONDITIONAL

#if optional_HAVE( IS_ASSIGNABLE )
    using std::is_assignable;
#else
    template< class T, class U > struct is_assignable : std11::true_type{};
#endif

#if optional_HAVE( IS_MOVE_CONSTRUCTIBLE )
    using std::is_move_constructible;
#else
    template< class T > struct is_move_constructible : std11::true_type{};
#endif

#if optional_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE )
    using std::is_nothrow_move_assignable;
#else
    template< class T > struct is_nothrow_move_assignable : std11::true_type{};
#endif

#if optional_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE )
    using std::is_nothrow_move_constructible;
#else
    template< class T > struct is_nothrow_move_constructible : std11::true_type{};
#endif

#if optional_HAVE( IS_TRIVIALLY_COPY_CONSTRUCTIBLE )
    using std::is_trivially_copy_constructible;
#else
    template< class T > struct is_trivially_copy_constructible : std11::true_type{};
#endif

#if optional_HAVE( IS_TRIVIALLY_MOVE_CONSTRUCTIBLE )
    using std::is_trivially_move_constructible;
#else
    template< class T > struct is_trivially_move_constructible : std11::true_type{};
#endif

} // namespace std11

#if optional_CPP11_OR_GREATER

/// type traits C++17:

namespace std17 {

#if optional_CPP17_OR_GREATER

using std::is_swappable;
using std::is_nothrow_swappable;

#elif optional_CPP11_OR_GREATER

namespace detail {

using std::swap;

struct is_swappable
{
    template< typename T, typename = decltype( swap( std::declval(), std::declval() ) ) >
    static std11::true_type test( int /*unused*/ );

    template< typename >
    static std11::false_type test(...);
};

struct is_nothrow_swappable
{
    // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):

    template< typename T >
    static constexpr bool satisfies()
    {
        return noexcept( swap( std::declval(), std::declval() ) );
    }

    template< typename T >
    static auto test( int /*unused*/ ) -> std11::integral_constant{}

    template< typename >
    static auto test(...) -> std11::false_type;
};

} // namespace detail

// is [nothow] swappable:

template< typename T >
struct is_swappable : decltype( detail::is_swappable::test(0) ){};

template< typename T >
struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test(0) ){};

#endif // optional_CPP17_OR_GREATER

} // namespace std17

/// type traits C++20:

namespace std20 {

template< typename T >
struct remove_cvref
{
    typedef typename std::remove_cv< typename std::remove_reference::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 ) - sizeof(T), sizeof(T) >::value };
};

template< typename List, size_t N >
struct type_of_size
{
    typedef typename std11::conditional<
        N == sizeof( typename List::head ),
            typename List::head,
            typename type_of_size::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() optional_is_default

    explicit 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

    explicit storage_t( value_type && v )
    {
        construct_value( std::move( v ) );
    }

    void construct_value( value_type && v )
    {
        ::new( const_cast(static_cast(value_ptr())) ) value_type( std::move( v ) );
    }

    template< class... Args >
    storage_t( nonstd_lite_in_place_t(T), Args&&... args )
    {
        emplace( std::forward(args)... );
    }

    template< class... Args >
    void emplace( Args&&... args )
    {
        ::new( const_cast(static_cast(value_ptr())) ) value_type( std::forward(args)... );
    }

    template< class U, class... Args >
    void emplace( std::initializer_list il, Args&&... args )
    {
        ::new( const_cast(static_cast(value_ptr())) ) value_type( il, std::forward(args)... );
    }

#endif

    void destruct_value()
    {
        value_ptr()->~T();
    }

    optional_nodiscard value_type const * value_ptr() const
    {
        return as();
    }

    value_type * value_ptr()
    {
        return as();
    }

    optional_nodiscard value_type const & value() const optional_ref_qual
    {
        return * value_ptr();
    }

    value_type & value() optional_ref_qual
    {
        return * value_ptr();
    }

#if optional_HAVE( REF_QUALIFIER )

    optional_nodiscard 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

    optional_nodiscard void * ptr() optional_noexcept
    {
        return &data;
    }

    optional_nodiscard void const * ptr() const optional_noexcept
    {
        return &data;
    }

    template 
    optional_nodiscard U * as()
    {
        return reinterpret_cast( ptr() );
    }

    template 
    optional_nodiscard U const * as() const
    {
        return reinterpret_cast( ptr() );
    }
};

} // namespace detail

/// disengaged state tag

struct nullopt_t
{
    struct init{};
    explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
};

#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

#if ! optional_CONFIG_NO_EXCEPTIONS

class optional_nodiscard bad_optional_access : public std::logic_error
{
public:
  explicit bad_optional_access()
  : logic_error( "bad optional access" ) {}
};

#endif //optional_CONFIG_NO_EXCEPTIONS

/// optional

template< typename T>
class optional
{
    optional_static_assert(( !std::is_same::value  ),
        "T in optional must not be of type 'nullopt_t'.")

    optional_static_assert(( !std::is_same::value ),
        "T in optional must not be of type 'in_place_t'.")

    optional_static_assert(( std::is_object::value && std::is_destructible::value && !std::is_array::value ),
        "T in optional must meet the Cpp17Destructible requirements.")

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
    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
    optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept
    : has_value_( false )
    , contained()
    {}

    // 2 - copy-construct
#if optional_CPP11_OR_GREATER
    // template< typename U = T
    //     optional_REQUIRES_T(
    //         std::is_copy_constructible::value
    //         || std11::is_trivially_copy_constructible::value
    //     )
    // >
#endif
    optional_constexpr14 optional( optional const & other )
    : 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
    template< typename U = T
        optional_REQUIRES_T(
            std11::is_move_constructible::value
            || std11::is_trivially_move_constructible::value
        )
    >
    optional_constexpr14 optional( optional && other )
    // NOLINTNEXTLINE( performance-noexcept-move-constructor )
        noexcept( std11::is_nothrow_move_constructible::value )
    : has_value_( other.has_value() )
    {
        if ( other.has_value() )
        {
            contained.construct_value( std::move( other.contained.value() ) );
        }
    }

    // 4a (C++11) - explicit converting copy-construct from optional
    template< typename U
        optional_REQUIRES_T(
            std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_convertible<     optional &       , T>::value
            && !std::is_convertible<     optional &&      , T>::value
            && !std::is_convertible<     optional const & , T>::value
            && !std::is_convertible<     optional const &&, T>::value
            && !std::is_convertible<               U const & , T>::value /*=> explicit */
        )
    >
    explicit optional( optional const & other )
    : has_value_( other.has_value() )
    {
        if ( other.has_value() )
        {
            contained.construct_value( T{ other.contained.value() } );
        }
    }
#endif // optional_CPP11_OR_GREATER

    // 4b (C++98 and later) - non-explicit converting copy-construct from optional
    template< typename U
#if optional_CPP11_OR_GREATER
        optional_REQUIRES_T(
            std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_convertible<     optional &       , T>::value
            && !std::is_convertible<     optional &&      , T>::value
            && !std::is_convertible<     optional const & , T>::value
            && !std::is_convertible<     optional const &&, T>::value
            &&  std::is_convertible<               U const & , T>::value /*=> non-explicit */
        )
#endif // optional_CPP11_OR_GREATER
    >
    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
    /*non-explicit*/ optional( optional const & other )
    : 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_REQUIRES_T(
            std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_convertible<     optional &       , T>::value
            && !std::is_convertible<     optional &&      , T>::value
            && !std::is_convertible<     optional const & , T>::value
            && !std::is_convertible<     optional const &&, T>::value
            && !std::is_convertible<                     U &&, T>::value /*=> explicit */
        )
    >
    explicit optional( optional && other
    )
    : has_value_( other.has_value() )
    {
        if ( other.has_value() )
        {
            contained.construct_value( T{ std::move( other.contained.value() ) } );
        }
    }

    // 5a (C++11) - non-explicit converting move-construct from optional
    template< typename U
        optional_REQUIRES_T(
            std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_convertible<     optional &       , T>::value
            && !std::is_convertible<     optional &&      , T>::value
            && !std::is_convertible<     optional const & , T>::value
            && !std::is_convertible<     optional const &&, T>::value
            &&  std::is_convertible<                     U &&, T>::value /*=> non-explicit */
        )
    >
    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
    /*non-explicit*/ optional( optional && other )
    : 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::value
        )
    >
    optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
    : has_value_( true )
    , contained( in_place, std::forward(args)... )
    {}

    // 7 (C++11) - in-place construct,  initializer-list
    template< typename U, typename... Args
        optional_REQUIRES_T(
            std::is_constructible::value
        )
    >
    optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list il, Args&&... args )
    : has_value_( true )
    , contained( T( il, std::forward(args)...) )
    {}

    // 8a (C++11) - explicit move construct from value
    template< typename U = T
        optional_REQUIRES_T(
            std::is_constructible::value
            && !std::is_same::value
            && !std::is_same::value
            && !std::is_convertible::value /*=> explicit */
        )
    >
    optional_constexpr explicit optional( U && value )
    : has_value_( true )
    , contained( nonstd_lite_in_place(T), std::forward( value ) )
    {}

    // 8b (C++11) - non-explicit move construct from value
    template< typename U = T
        optional_REQUIRES_T(
            std::is_constructible::value
            && !std::is_same::value
            && !std::is_same::value
            && std::is_convertible::value /*=> non-explicit */
        )
    >
    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
    optional_constexpr /*non-explicit*/ optional( U && value )
    : has_value_( true )
    , contained( nonstd_lite_in_place(T), std::forward( 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 /*unused*/) optional_noexcept
    {
        reset();
        return *this;
    }

    // 2 (C++98and later) - copy-assign from optional
#if optional_CPP11_OR_GREATER
    // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
    optional_REQUIRES_R(
        optional &,
        true
//      std::is_copy_constructible::value
//      && std::is_copy_assignable::value
    )
    operator=( optional const & other )
        noexcept(
            std11::is_nothrow_move_assignable::value
            && std11::is_nothrow_move_constructible::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
    // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
    optional_REQUIRES_R(
        optional &,
        true
//      std11::is_move_constructible::value
//      && std::is_move_assignable::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 >
        // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
        optional_REQUIRES_R(
            optional &,
            std::is_constructible::value
            && std11::is_assignable::value
            && !std::is_same::value
            && !std::is_same::value
            && !(std::is_scalar::value && std::is_same::value)
        )
    operator=( U && value )
    {
        if ( has_value() )
        {
            contained.value() = std::forward( value );
        }
        else
        {
            initialize( T( std::forward( 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
        // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
        optional_REQUIRES_R(
            optional&,
            std::is_constructible<  T , U const &>::value
            &&  std11::is_assignable< T&, U const &>::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_convertible<     optional &       , T>::value
            && !std::is_convertible<     optional &&      , T>::value
            && !std::is_convertible<     optional const & , T>::value
            && !std::is_convertible<     optional const &&, T>::value
            && !std11::is_assignable<  T&, optional &          >::value
            && !std11::is_assignable<  T&, optional &&         >::value
            && !std11::is_assignable<  T&, optional const &    >::value
            && !std11::is_assignable<  T&, optional const &&   >::value
        )
#else
    optional&
#endif // optional_CPP11_OR_GREATER
    operator=( optional const & other )
    {
        return *this = optional( other );
    }

#if optional_CPP11_OR_GREATER

    // 6 (C++11) -  converting move-assign from optional
    template< typename U >
        // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
        optional_REQUIRES_R(
            optional&,
            std::is_constructible<  T , U>::value
            &&  std11::is_assignable< T&, U>::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_constructible::value
            && !std::is_convertible<     optional &       , T>::value
            && !std::is_convertible<     optional &&      , T>::value
            && !std::is_convertible<     optional const & , T>::value
            && !std::is_convertible<     optional const &&, T>::value
            && !std11::is_assignable<  T&, optional &          >::value
            && !std11::is_assignable<  T&, optional &&         >::value
            && !std11::is_assignable<  T&, optional const &    >::value
            && !std11::is_assignable<  T&, optional const &&   >::value
        )
    operator=( optional && other )
    {
        return *this = optional( std::move( other ) );
    }

    // 7 (C++11) - emplace
    template< typename... Args
        optional_REQUIRES_T(
            std::is_constructible::value
        )
    >
    T& emplace( Args&&... args )
    {
        *this = nullopt;
        contained.emplace( std::forward(args)...  );
        has_value_ = true;
        return contained.value();
    }

    // 8 (C++11) - emplace, initializer-list
    template< typename U, typename... Args
        optional_REQUIRES_T(
            std::is_constructible::value
        )
    >
    T& emplace( std::initializer_list il, Args&&... args )
    {
        *this = nullopt;
        contained.emplace( il, std::forward(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(
            std11::is_nothrow_move_constructible::value
            && std17::is_nothrow_swappable::value
        )
#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( std11::move(*other) ); other.reset(); }
        else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**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_HAVE( REF_QUALIFIER )

    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

    // NOLINTNEXTLINE( modernize-use-nodiscard )
    /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept
    {
        return has_value_;
    }

    // NOLINTNEXTLINE( modernize-use-nodiscard )
    /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual
    {
#if optional_CONFIG_NO_EXCEPTIONS
        assert( has_value() );
#else
        if ( ! has_value() )
        {
            throw bad_optional_access();
        }
#endif
        return contained.value();
    }

    optional_constexpr14 value_type & value() optional_ref_qual
    {
#if optional_CONFIG_NO_EXCEPTIONS
        assert( has_value() );
#else
        if ( ! has_value() )
        {
            throw bad_optional_access();
        }
#endif
        return contained.value();
    }

#if optional_HAVE( REF_QUALIFIER )  &&  ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )

    // NOLINTNEXTLINE( modernize-use-nodiscard )
    /*optional_nodiscard*/ optional_constexpr 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_HAVE( REF_QUALIFIER )

    template< typename U >
    optional_constexpr value_type value_or( U && v ) const optional_ref_qual
    {
        return has_value() ? contained.value() : static_cast(std::forward( v ) );
    }

    template< typename U >
    optional_constexpr14 value_type value_or( U && v ) optional_refref_qual
    {
#if optional_COMPILER_CLANG_VERSION
        return has_value() ? /*std::move*/( contained.value() ) : static_cast(std::forward( v ) );
#else
        return has_value() ? std::move( contained.value() ) : static_cast(std::forward( v ) );
#endif
    }

#else

    template< typename U >
    optional_constexpr value_type value_or( U const & v ) const
    {
        return has_value() ? contained.value() : static_cast( v );
    }

#endif // optional_HAVE( REF_QUALIFIER )

#if !optional_CONFIG_NO_EXTENSIONS
#if  optional_HAVE( REF_QUALIFIER )

    template< typename F >
    optional_constexpr value_type value_or_eval( F f ) const &
    {
        return has_value() ? contained.value() : f();
    }

    template< typename F >
    optional_constexpr14 value_type value_or_eval( F f ) &&
    {
        if ( has_value() )
        {
            return std::move( contained.value() );
        }
        else
        {
            return f();
        }
    }

#else

    template< typename F >
    optional_constexpr value_type value_or_eval( F f ) const
    {
        return has_value() ? contained.value() : f();
    }

#endif //  optional_HAVE( REF_QUALIFIER )
#endif // !optional_CONFIG_NO_EXTENSIONS

    // 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::forward( value ) );
        has_value_ = true;
    }

#endif

private:
    bool has_value_;
    detail::storage_t< value_type > contained;

};

// Relational operators

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator==( optional const & x, optional const & y )
{
    return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator!=( optional const & x, optional const & y )
{
    return !(x == y);
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator>( optional const & x, optional const & y )
{
    return (y < x);
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator>=( optional const & x, optional const & y )
{
    return !(x < y);
}

// Comparison with nullopt

template< typename T >
optional_nodiscard optional_constexpr bool operator==( optional const & x, nullopt_t /*unused*/ ) optional_noexcept
{
    return (!x);
}

template< typename T >
optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional const & x ) optional_noexcept
{
    return (!x);
}

template< typename T >
optional_nodiscard optional_constexpr bool operator!=( optional const & x, nullopt_t /*unused*/ ) optional_noexcept
{
    return bool(x);
}

template< typename T >
optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional const & x ) optional_noexcept
{
    return bool(x);
}

template< typename T >
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator>( optional const & x, nullopt_t /*unused*/ ) optional_noexcept
{
    return bool(x);
}

template< typename T >
optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional const & /*unused*/ ) optional_noexcept
{
    return false;
}

template< typename T >
optional_nodiscard optional_constexpr bool operator>=( optional const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
{
    return true;
}

template< typename T >
optional_nodiscard optional_constexpr bool operator>=( nullopt_t /*unused*/, optional const & x ) optional_noexcept
{
    return (!x);
}

// Comparison with T

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator==( optional const & x, U const & v )
{
    return bool(x) ? *x == v : false;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator==( U const & v, optional const & x )
{
    return bool(x) ? v == *x : false;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator!=( optional const & x, U const & v )
{
    return bool(x) ? *x != v : true;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator!=( U const & v, optional const & x )
{
    return bool(x) ? v != *x : true;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator
optional_nodiscard optional_constexpr bool operator v : false;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator>( U const & v, optional const & x )
{
    return bool(x) ? v > *x : true;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator>=( optional const & x, U const & v )
{
    return bool(x) ? *x >= v : false;
}

template< typename T, typename U >
optional_nodiscard optional_constexpr bool operator>=( U const & v, optional const & x )
{
    return bool(x) ? v >= *x : true;
}

// Specialized algorithms

template< typename T
#if optional_CPP11_OR_GREATER
    optional_REQUIRES_T(
        std11::is_move_constructible::value
        && std17::is_swappable::value )
#endif
>
void swap( optional & x, optional & 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::type > make_optional( T && value )
{
    return optional< typename std::decay::type >( std::forward( value ) );
}

template< typename T, typename...Args >
optional_constexpr optional make_optional( Args&&... args )
{
    return optional( nonstd_lite_in_place(T), std::forward(args)...);
}

template< typename T, typename U, typename... Args >
optional_constexpr optional make_optional( std::initializer_list il, Args&&... args )
{
    return optional( nonstd_lite_in_place(T), il, std::forward(args)...);
}

#else

template< typename T >
optional make_optional( T const & value )
{
    return optional( value );
}

#endif // optional_CPP11_OR_GREATER

} // namespace optional_lite

using optional_lite::optional;
using optional_lite::nullopt_t;
using optional_lite::nullopt;

#if ! optional_CONFIG_NO_EXCEPTIONS
using optional_lite::bad_optional_access;
#endif

using optional_lite::make_optional;

} // namespace nonstd

#if optional_CPP11_OR_GREATER

// specialize the std::hash algorithm:

namespace std {

template< class T >
struct hash< nonstd::optional >
{
public:
    std::size_t operator()( nonstd::optional const & v ) const optional_noexcept
    {
        return bool( v ) ? std::hash{}( *v ) : 0;
    }
};

} //namespace std

#endif // optional_CPP11_OR_GREATER

#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__GNUC__)
# pragma GCC   diagnostic pop
#elif defined(_MSC_VER )
# pragma warning( pop )
#endif

#endif // optional_USES_STD_OPTIONAL

#endif // NONSTD_OPTIONAL_LITE_HPP

Web Proxy Viewer  |  New URL  |  Original Page