2 // Copyright (c) 2014-2021 Martin Moene
4 // https://github.com/martinmoene/optional-lite
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef NONSTD_OPTIONAL_LITE_HPP
12 #define NONSTD_OPTIONAL_LITE_HPP
14 #define optional_lite_MAJOR 3
15 #define optional_lite_MINOR 6
16 #define optional_lite_PATCH 0
18 #define optional_lite_VERSION optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH)
20 #define optional_STRINGIFY( x ) optional_STRINGIFY_( x )
21 #define optional_STRINGIFY_( x ) #x
23 // optional-lite configuration:
25 #define optional_OPTIONAL_DEFAULT 0
26 #define optional_OPTIONAL_NONSTD 1
27 #define optional_OPTIONAL_STD 2
29 // tweak header support:
32 # if __has_include(<nonstd/optional.tweak.hpp>)
33 # include <nonstd/optional.tweak.hpp>
35 #define optional_HAVE_TWEAK_HEADER 1
37 #define optional_HAVE_TWEAK_HEADER 0
38 //# pragma message("optional.hpp: Note: Tweak header not supported.")
41 // optional selection and configuration:
43 #if !defined( optional_CONFIG_SELECT_OPTIONAL )
44 # define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
47 // Control presence of extensions:
49 #ifndef optional_CONFIG_NO_EXTENSIONS
50 #define optional_CONFIG_NO_EXTENSIONS 0
53 // Control presence of exception handling (try and auto discover):
55 #ifndef optional_CONFIG_NO_EXCEPTIONS
56 # if defined(_MSC_VER)
57 # include <cstddef> // for _HAS_EXCEPTIONS
59 # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS))
60 # define optional_CONFIG_NO_EXCEPTIONS 0
62 # define optional_CONFIG_NO_EXCEPTIONS 1
66 // C++ language version detection (C++23 is speculative):
67 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
69 #ifndef optional_CPLUSPLUS
70 # if defined(_MSVC_LANG ) && !defined(__clang__)
71 # define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
73 # define optional_CPLUSPLUS __cplusplus
77 #define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L )
78 #define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L )
79 #define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L )
80 #define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L )
81 #define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L )
82 #define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202002L )
83 #define optional_CPP23_OR_GREATER ( optional_CPLUSPLUS >= 202300L )
85 // C++ language version (represent 98 as 3):
87 #define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
89 // Use C++17 std::optional if available and requested:
91 #if optional_CPP17_OR_GREATER && defined(__has_include )
92 # if __has_include( <optional> )
93 # define optional_HAVE_STD_OPTIONAL 1
95 # define optional_HAVE_STD_OPTIONAL 0
98 # define optional_HAVE_STD_OPTIONAL 0
101 #define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
104 // in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
107 #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
108 #define nonstd_lite_HAVE_IN_PLACE_TYPES 1
110 // C++17 std::in_place in <utility>:
112 #if optional_CPP17_OR_GREATER
119 using std::in_place_type;
120 using std::in_place_index;
121 using std::in_place_t;
122 using std::in_place_type_t;
123 using std::in_place_index_t;
125 #define nonstd_lite_in_place_t( T) std::in_place_t
126 #define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
127 #define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
129 #define nonstd_lite_in_place( T) std::in_place_t{}
130 #define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
131 #define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
133 } // namespace nonstd
135 #else // optional_CPP17_OR_GREATER
143 struct in_place_type_tag {};
145 template< std::size_t K >
146 struct in_place_index_tag {};
148 } // namespace detail
150 struct in_place_t {};
153 inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
158 template< std::size_t K >
159 inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
165 inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
170 template< std::size_t K >
171 inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
176 // mimic templated typedef:
178 #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
179 #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
180 #define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
182 #define nonstd_lite_in_place( T) nonstd::in_place_type<T>
183 #define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
184 #define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
186 } // namespace nonstd
188 #endif // optional_CPP17_OR_GREATER
189 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
192 // Using std::optional:
195 #if optional_USES_STD_OPTIONAL
202 using std::bad_optional_access;
206 using std::nullopt_t;
208 using std::operator==;
209 using std::operator!=;
210 using std::operator<;
211 using std::operator<=;
212 using std::operator>;
213 using std::operator>=;
214 using std::make_optional;
218 #else // optional_USES_STD_OPTIONAL
223 // optional-lite alignment configuration:
225 #ifndef optional_CONFIG_MAX_ALIGN_HACK
226 # define optional_CONFIG_MAX_ALIGN_HACK 0
229 #ifndef optional_CONFIG_ALIGN_AS
230 // no default, used in #if defined()
233 #ifndef optional_CONFIG_ALIGN_AS_FALLBACK
234 # define optional_CONFIG_ALIGN_AS_FALLBACK double
237 // Compiler warning suppression:
239 #if defined(__clang__)
240 # pragma clang diagnostic push
241 # pragma clang diagnostic ignored "-Wundef"
242 #elif defined(__GNUC__)
243 # pragma GCC diagnostic push
244 # pragma GCC diagnostic ignored "-Wundef"
245 #elif defined(_MSC_VER )
246 # pragma warning( push )
249 // half-open range [lo..hi):
250 #define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
252 // Compiler versions:
254 // MSVC++ 6.0 _MSC_VER == 1200 optional_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
255 // MSVC++ 7.0 _MSC_VER == 1300 optional_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
256 // MSVC++ 7.1 _MSC_VER == 1310 optional_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
257 // MSVC++ 8.0 _MSC_VER == 1400 optional_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
258 // MSVC++ 9.0 _MSC_VER == 1500 optional_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
259 // MSVC++ 10.0 _MSC_VER == 1600 optional_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
260 // MSVC++ 11.0 _MSC_VER == 1700 optional_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
261 // MSVC++ 12.0 _MSC_VER == 1800 optional_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
262 // MSVC++ 14.0 _MSC_VER == 1900 optional_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
263 // MSVC++ 14.1 _MSC_VER >= 1910 optional_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
264 // MSVC++ 14.2 _MSC_VER >= 1920 optional_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
266 #if defined(_MSC_VER ) && !defined(__clang__)
267 # define optional_COMPILER_MSVC_VER (_MSC_VER )
268 # define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
270 # define optional_COMPILER_MSVC_VER 0
271 # define optional_COMPILER_MSVC_VERSION 0
274 #define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * (major) + (minor) ) + (patch) )
276 #if defined(__GNUC__) && !defined(__clang__)
277 # define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
279 # define optional_COMPILER_GNUC_VERSION 0
282 #if defined(__clang__)
283 # define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
285 # define optional_COMPILER_CLANG_VERSION 0
288 #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
289 # pragma warning( disable: 4345 ) // initialization behavior changed
292 #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
293 # pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const'
296 // Presence of language and library features:
298 #define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
301 # define optional_HAS_CPP0X _HAS_CPP0X
303 # define optional_HAS_CPP0X 0
306 // Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
308 #if optional_COMPILER_MSVC_VER >= 1900
309 # undef optional_CPP11_OR_GREATER
310 # define optional_CPP11_OR_GREATER 1
313 #define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
314 #define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
315 #define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
316 #define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
317 #define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
318 #define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
320 #define optional_CPP14_000 (optional_CPP14_OR_GREATER)
321 #define optional_CPP17_000 (optional_CPP17_OR_GREATER)
323 // clang >= 2.9, gcc >= 4.9, msvc >= vc14.0/1900 (vs15):
324 #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))
326 // clang >= 3.5, msvc >= vc11 (vs12):
327 #define optional_CPP11_110_C350 ( optional_CPP11_110 && !optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) )
329 // clang >= 3.5, gcc >= 5.0, msvc >= vc11 (vs12):
330 #define optional_CPP11_110_C350_G500 \
331 ( optional_CPP11_110 && \
332 !( optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) \
333 || optional_BETWEEN( optional_COMPILER_GNUC_VERSION , 1, 500 ) ) )
335 // Presence of C++11 language features:
337 #define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
338 #define optional_HAVE_IS_DEFAULT optional_CPP11_140
339 #define optional_HAVE_NOEXCEPT optional_CPP11_140
340 #define optional_HAVE_NULLPTR optional_CPP11_100
341 #define optional_HAVE_REF_QUALIFIER optional_CPP11_140_C290_G490
342 #define optional_HAVE_STATIC_ASSERT optional_CPP11_110
343 #define optional_HAVE_INITIALIZER_LIST optional_CPP11_140
345 // Presence of C++14 language features:
347 #define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
349 // Presence of C++17 language features:
351 #define optional_HAVE_NODISCARD optional_CPP17_000
353 // Presence of C++ library features:
355 #define optional_HAVE_CONDITIONAL optional_CPP11_120
356 #define optional_HAVE_REMOVE_CV optional_CPP11_120
357 #define optional_HAVE_TYPE_TRAITS optional_CPP11_90
359 #define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
360 #define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )
362 #define optional_HAVE_IS_ASSIGNABLE optional_CPP11_110_C350
363 #define optional_HAVE_IS_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350
364 #define optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE optional_CPP11_110_C350
365 #define optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350
366 #define optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE optional_CPP11_110_C350_G500
367 #define optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350_G500
369 // C++ feature usage:
371 #if optional_HAVE( CONSTEXPR_11 )
372 # define optional_constexpr constexpr
374 # define optional_constexpr /*constexpr*/
377 #if optional_HAVE( IS_DEFAULT )
378 # define optional_is_default = default;
380 # define optional_is_default {}
383 #if optional_HAVE( CONSTEXPR_14 )
384 # define optional_constexpr14 constexpr
386 # define optional_constexpr14 /*constexpr*/
389 #if optional_HAVE( NODISCARD )
390 # define optional_nodiscard [[nodiscard]]
392 # define optional_nodiscard /*[[nodiscard]]*/
395 #if optional_HAVE( NOEXCEPT )
396 # define optional_noexcept noexcept
398 # define optional_noexcept /*noexcept*/
401 #if optional_HAVE( NULLPTR )
402 # define optional_nullptr nullptr
404 # define optional_nullptr NULL
407 #if optional_HAVE( REF_QUALIFIER )
408 // NOLINTNEXTLINE( bugprone-macro-parentheses )
409 # define optional_ref_qual &
410 # define optional_refref_qual &&
412 # define optional_ref_qual /*&*/
413 # define optional_refref_qual /*&&*/
416 #if optional_HAVE( STATIC_ASSERT )
417 # define optional_static_assert(expr, text) static_assert(expr, text);
419 # define optional_static_assert(expr, text) /*static_assert(expr, text);*/
422 // additional includes:
424 #if optional_CONFIG_NO_EXCEPTIONS
425 // already included: <cassert>
427 # include <stdexcept>
430 #if optional_CPP11_OR_GREATER
431 # include <functional>
434 #if optional_HAVE( INITIALIZER_LIST )
435 # include <initializer_list>
438 #if optional_HAVE( TYPE_TRAITS )
439 # include <type_traits>
440 #elif optional_HAVE( TR1_TYPE_TRAITS )
441 # include <tr1/type_traits>
446 #if optional_CPP11_OR_GREATER
448 #define optional_REQUIRES_0(...) \
449 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
451 #define optional_REQUIRES_T(...) \
452 , typename std::enable_if< (__VA_ARGS__), int >::type = 0
454 #define optional_REQUIRES_R(R, ...) \
455 typename std::enable_if< (__VA_ARGS__), R>::type
457 #define optional_REQUIRES_A(...) \
458 , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
466 namespace nonstd { namespace optional_lite {
470 template< class T, T v > struct integral_constant { enum { value = v }; };
471 template< bool B > struct bool_constant : integral_constant<bool, B>{};
473 typedef bool_constant< true > true_type;
474 typedef bool_constant< false > false_type;
476 #if optional_CPP11_OR_GREATER
479 template< typename T > T & move( T & t ) { return t; }
482 #if optional_HAVE( CONDITIONAL )
483 using std::conditional;
485 template< bool B, typename T, typename F > struct conditional { typedef T type; };
486 template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
487 #endif // optional_HAVE_CONDITIONAL
489 #if optional_HAVE( IS_ASSIGNABLE )
490 using std::is_assignable;
492 template< class T, class U > struct is_assignable : std11::true_type{};
495 #if optional_HAVE( IS_MOVE_CONSTRUCTIBLE )
496 using std::is_move_constructible;
498 template< class T > struct is_move_constructible : std11::true_type{};
501 #if optional_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE )
502 using std::is_nothrow_move_assignable;
504 template< class T > struct is_nothrow_move_assignable : std11::true_type{};
507 #if optional_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE )
508 using std::is_nothrow_move_constructible;
510 template< class T > struct is_nothrow_move_constructible : std11::true_type{};
513 #if optional_HAVE( IS_TRIVIALLY_COPY_CONSTRUCTIBLE )
514 using std::is_trivially_copy_constructible;
516 template< class T > struct is_trivially_copy_constructible : std11::true_type{};
519 #if optional_HAVE( IS_TRIVIALLY_MOVE_CONSTRUCTIBLE )
520 using std::is_trivially_move_constructible;
522 template< class T > struct is_trivially_move_constructible : std11::true_type{};
527 #if optional_CPP11_OR_GREATER
529 /// type traits C++17:
533 #if optional_CPP17_OR_GREATER
535 using std::is_swappable;
536 using std::is_nothrow_swappable;
538 #elif optional_CPP11_OR_GREATER
546 template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
547 static std11::true_type test( int /*unused*/ );
550 static std11::false_type test(...);
553 struct is_nothrow_swappable
555 // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
557 template< typename T >
558 static constexpr bool satisfies()
560 return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
563 template< typename T >
564 static auto test( int /*unused*/ ) -> std11::integral_constant<bool, satisfies<T>()>{}
567 static auto test(...) -> std11::false_type;
570 } // namespace detail
572 // is [nothow] swappable:
574 template< typename T >
575 struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
577 template< typename T >
578 struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
580 #endif // optional_CPP17_OR_GREATER
584 /// type traits C++20:
588 template< typename T >
591 typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
596 #endif // optional_CPP11_OR_GREATER
600 template< typename T >
609 template< typename Head, typename Tail >
616 #if optional_CONFIG_MAX_ALIGN_HACK
618 // Max align, use most restricted type for alignment:
620 #define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ )
621 #define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
622 #define optional_UNIQUE3( name, line ) name ## line
624 #define optional_ALIGN_TYPE( type ) \
625 type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
627 template< typename T >
628 struct struct_t { T _; };
632 optional_ALIGN_TYPE( char );
633 optional_ALIGN_TYPE( short int );
634 optional_ALIGN_TYPE( int );
635 optional_ALIGN_TYPE( long int );
636 optional_ALIGN_TYPE( float );
637 optional_ALIGN_TYPE( double );
638 optional_ALIGN_TYPE( long double );
639 optional_ALIGN_TYPE( char * );
640 optional_ALIGN_TYPE( short int * );
641 optional_ALIGN_TYPE( int * );
642 optional_ALIGN_TYPE( long int * );
643 optional_ALIGN_TYPE( float * );
644 optional_ALIGN_TYPE( double * );
645 optional_ALIGN_TYPE( long double * );
646 optional_ALIGN_TYPE( void * );
648 #ifdef HAVE_LONG_LONG
649 optional_ALIGN_TYPE( long long );
654 Unknown ( * optional_UNIQUE(_) )( Unknown );
655 Unknown * Unknown::* optional_UNIQUE(_);
656 Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
658 struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_);
659 struct_t< Unknown * Unknown::* > optional_UNIQUE(_);
660 struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
663 #undef optional_UNIQUE
664 #undef optional_UNIQUE2
665 #undef optional_UNIQUE3
667 #undef optional_ALIGN_TYPE
669 #elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
671 // Use user-specified type for alignment:
673 #define optional_ALIGN_AS( unused ) \
674 optional_CONFIG_ALIGN_AS
676 #else // optional_CONFIG_MAX_ALIGN_HACK
678 // Determine POD type to use for alignment:
680 #define optional_ALIGN_AS( to_align ) \
681 typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
683 template< typename T >
686 template< typename T >
687 struct alignment_of_hack
694 template< size_t A, size_t S >
695 struct alignment_logic
697 enum { value = A < S ? A : S };
700 template< typename T >
703 enum { value = alignment_logic<
704 sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
707 template< typename List, size_t N >
710 typedef typename std11::conditional<
711 N == sizeof( typename List::head ),
713 typename type_of_size<typename List::tail, N >::type >::type type;
717 struct type_of_size< nulltype, N >
719 typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
722 template< typename T>
723 struct struct_t { T _; };
725 #define optional_ALIGN_TYPE( type ) \
726 typelist< type , typelist< struct_t< type >
731 optional_ALIGN_TYPE( char ),
732 optional_ALIGN_TYPE( short ),
733 optional_ALIGN_TYPE( int ),
734 optional_ALIGN_TYPE( long ),
735 optional_ALIGN_TYPE( float ),
736 optional_ALIGN_TYPE( double ),
737 optional_ALIGN_TYPE( long double ),
739 optional_ALIGN_TYPE( char *),
740 optional_ALIGN_TYPE( short * ),
741 optional_ALIGN_TYPE( int * ),
742 optional_ALIGN_TYPE( long * ),
743 optional_ALIGN_TYPE( float * ),
744 optional_ALIGN_TYPE( double * ),
745 optional_ALIGN_TYPE( long double * ),
747 optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
748 optional_ALIGN_TYPE( Unknown * Unknown::* ),
749 optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
752 > > > > > > > > > > > > > >
753 > > > > > > > > > > > > > >
757 #undef optional_ALIGN_TYPE
759 #endif // optional_CONFIG_MAX_ALIGN_HACK
761 /// C++03 constructed union to hold value.
763 template< typename T >
767 // template< typename > friend class optional;
769 typedef T value_type;
771 storage_t() optional_is_default
773 explicit storage_t( value_type const & v )
775 construct_value( v );
778 void construct_value( value_type const & v )
780 ::new( value_ptr() ) value_type( v );
783 #if optional_CPP11_OR_GREATER
785 explicit storage_t( value_type && v )
787 construct_value( std::move( v ) );
790 void construct_value( value_type && v )
792 ::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( std::move( v ) );
795 template< class... Args >
796 storage_t( nonstd_lite_in_place_t(T), Args&&... args )
798 emplace( std::forward<Args>(args)... );
801 template< class... Args >
802 void emplace( Args&&... args )
804 ::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( std::forward<Args>(args)... );
807 template< class U, class... Args >
808 void emplace( std::initializer_list<U> il, Args&&... args )
810 ::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( il, std::forward<Args>(args)... );
815 void destruct_value()
820 optional_nodiscard value_type const * value_ptr() const
822 return as<value_type>();
825 value_type * value_ptr()
827 return as<value_type>();
830 optional_nodiscard value_type const & value() const optional_ref_qual
832 return * value_ptr();
835 value_type & value() optional_ref_qual
837 return * value_ptr();
840 #if optional_HAVE( REF_QUALIFIER )
842 optional_nodiscard value_type const && value() const optional_refref_qual
844 return std::move( value() );
847 value_type && value() optional_refref_qual
849 return std::move( value() );
854 #if optional_CPP11_OR_GREATER
856 using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
857 aligned_storage_t data;
859 #elif optional_CONFIG_MAX_ALIGN_HACK
861 typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
864 aligned_storage_t data;
867 typedef optional_ALIGN_AS(value_type) align_as_type;
869 typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
870 aligned_storage_t data;
872 # undef optional_ALIGN_AS
874 #endif // optional_CONFIG_MAX_ALIGN_HACK
876 optional_nodiscard void * ptr() optional_noexcept
881 optional_nodiscard void const * ptr() const optional_noexcept
886 template <typename U>
887 optional_nodiscard U * as()
889 return reinterpret_cast<U*>( ptr() );
892 template <typename U>
893 optional_nodiscard U const * as() const
895 return reinterpret_cast<U const *>( ptr() );
899 } // namespace detail
901 /// disengaged state tag
906 explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
909 #if optional_HAVE( CONSTEXPR_11 )
910 constexpr nullopt_t nullopt{ nullopt_t::init{} };
912 // extra parenthesis to prevent the most vexing parse:
913 const nullopt_t nullopt(( nullopt_t::init() ));
916 /// optional access error
918 #if ! optional_CONFIG_NO_EXCEPTIONS
920 class bad_optional_access : public std::logic_error
923 explicit bad_optional_access()
924 : logic_error( "bad optional access" ) {}
927 #endif //optional_CONFIG_NO_EXCEPTIONS
931 template< typename T>
934 optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, nullopt_t>::value ),
935 "T in optional<T> must not be of type 'nullopt_t'.")
937 optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, in_place_t>::value ),
938 "T in optional<T> must not be of type 'in_place_t'.")
940 optional_static_assert(( std::is_object<T>::value && std::is_destructible<T>::value && !std::is_array<T>::value ),
941 "T in optional<T> must meet the Cpp17Destructible requirements.")
944 template< typename > friend class optional;
946 typedef void (optional::*safe_bool)() const;
949 typedef T value_type;
951 // x.x.3.1, constructors
953 // 1a - default construct
954 optional_constexpr optional() optional_noexcept
955 : has_value_( false )
959 // 1b - construct explicitly empty
960 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
961 optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept
962 : has_value_( false )
966 // 2 - copy-construct
967 #if optional_CPP11_OR_GREATER
968 // template< typename U = T
969 // optional_REQUIRES_T(
970 // std::is_copy_constructible<U>::value
971 // || std11::is_trivially_copy_constructible<U>::value
975 optional_constexpr14 optional( optional const & other )
976 : has_value_( other.has_value() )
978 if ( other.has_value() )
980 contained.construct_value( other.contained.value() );
984 #if optional_CPP11_OR_GREATER
986 // 3 (C++11) - move-construct from optional
987 template< typename U = T
989 std11::is_move_constructible<U>::value
990 || std11::is_trivially_move_constructible<U>::value
993 optional_constexpr14 optional( optional && other )
994 // NOLINTNEXTLINE( performance-noexcept-move-constructor )
995 noexcept( std11::is_nothrow_move_constructible<T>::value )
996 : has_value_( other.has_value() )
998 if ( other.has_value() )
1000 contained.construct_value( std::move( other.contained.value() ) );
1004 // 4a (C++11) - explicit converting copy-construct from optional
1005 template< typename U
1006 optional_REQUIRES_T(
1007 std::is_constructible<T, U const &>::value
1008 && !std::is_constructible<T, optional<U> & >::value
1009 && !std::is_constructible<T, optional<U> && >::value
1010 && !std::is_constructible<T, optional<U> const & >::value
1011 && !std::is_constructible<T, optional<U> const && >::value
1012 && !std::is_convertible< optional<U> & , T>::value
1013 && !std::is_convertible< optional<U> && , T>::value
1014 && !std::is_convertible< optional<U> const & , T>::value
1015 && !std::is_convertible< optional<U> const &&, T>::value
1016 && !std::is_convertible< U const & , T>::value /*=> explicit */
1019 explicit optional( optional<U> const & other )
1020 : has_value_( other.has_value() )
1022 if ( other.has_value() )
1024 contained.construct_value( T{ other.contained.value() } );
1027 #endif // optional_CPP11_OR_GREATER
1029 // 4b (C++98 and later) - non-explicit converting copy-construct from optional
1030 template< typename U
1031 #if optional_CPP11_OR_GREATER
1032 optional_REQUIRES_T(
1033 std::is_constructible<T, U const &>::value
1034 && !std::is_constructible<T, optional<U> & >::value
1035 && !std::is_constructible<T, optional<U> && >::value
1036 && !std::is_constructible<T, optional<U> const & >::value
1037 && !std::is_constructible<T, optional<U> const && >::value
1038 && !std::is_convertible< optional<U> & , T>::value
1039 && !std::is_convertible< optional<U> && , T>::value
1040 && !std::is_convertible< optional<U> const & , T>::value
1041 && !std::is_convertible< optional<U> const &&, T>::value
1042 && std::is_convertible< U const & , T>::value /*=> non-explicit */
1044 #endif // optional_CPP11_OR_GREATER
1046 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1047 /*non-explicit*/ optional( optional<U> const & other )
1048 : has_value_( other.has_value() )
1050 if ( other.has_value() )
1052 contained.construct_value( other.contained.value() );
1056 #if optional_CPP11_OR_GREATER
1058 // 5a (C++11) - explicit converting move-construct from optional
1059 template< typename U
1060 optional_REQUIRES_T(
1061 std::is_constructible<T, U &&>::value
1062 && !std::is_constructible<T, optional<U> & >::value
1063 && !std::is_constructible<T, optional<U> && >::value
1064 && !std::is_constructible<T, optional<U> const & >::value
1065 && !std::is_constructible<T, optional<U> const && >::value
1066 && !std::is_convertible< optional<U> & , T>::value
1067 && !std::is_convertible< optional<U> && , T>::value
1068 && !std::is_convertible< optional<U> const & , T>::value
1069 && !std::is_convertible< optional<U> const &&, T>::value
1070 && !std::is_convertible< U &&, T>::value /*=> explicit */
1073 explicit optional( optional<U> && other
1075 : has_value_( other.has_value() )
1077 if ( other.has_value() )
1079 contained.construct_value( T{ std::move( other.contained.value() ) } );
1083 // 5a (C++11) - non-explicit converting move-construct from optional
1084 template< typename U
1085 optional_REQUIRES_T(
1086 std::is_constructible<T, U &&>::value
1087 && !std::is_constructible<T, optional<U> & >::value
1088 && !std::is_constructible<T, optional<U> && >::value
1089 && !std::is_constructible<T, optional<U> const & >::value
1090 && !std::is_constructible<T, optional<U> const && >::value
1091 && !std::is_convertible< optional<U> & , T>::value
1092 && !std::is_convertible< optional<U> && , T>::value
1093 && !std::is_convertible< optional<U> const & , T>::value
1094 && !std::is_convertible< optional<U> const &&, T>::value
1095 && std::is_convertible< U &&, T>::value /*=> non-explicit */
1098 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1099 /*non-explicit*/ optional( optional<U> && other )
1100 : has_value_( other.has_value() )
1102 if ( other.has_value() )
1104 contained.construct_value( std::move( other.contained.value() ) );
1108 // 6 (C++11) - in-place construct
1109 template< typename... Args
1110 optional_REQUIRES_T(
1111 std::is_constructible<T, Args&&...>::value
1114 optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
1115 : has_value_( true )
1116 , contained( in_place, std::forward<Args>(args)... )
1119 // 7 (C++11) - in-place construct, initializer-list
1120 template< typename U, typename... Args
1121 optional_REQUIRES_T(
1122 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1125 optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
1126 : has_value_( true )
1127 , contained( T( il, std::forward<Args>(args)...) )
1130 // 8a (C++11) - explicit move construct from value
1131 template< typename U = T
1132 optional_REQUIRES_T(
1133 std::is_constructible<T, U&&>::value
1134 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1135 && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1136 && !std::is_convertible<U&&, T>::value /*=> explicit */
1139 optional_constexpr explicit optional( U && value )
1140 : has_value_( true )
1141 , contained( nonstd_lite_in_place(T), std::forward<U>( value ) )
1144 // 8b (C++11) - non-explicit move construct from value
1145 template< typename U = T
1146 optional_REQUIRES_T(
1147 std::is_constructible<T, U&&>::value
1148 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1149 && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1150 && std::is_convertible<U&&, T>::value /*=> non-explicit */
1153 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1154 optional_constexpr /*non-explicit*/ optional( U && value )
1155 : has_value_( true )
1156 , contained( nonstd_lite_in_place(T), std::forward<U>( value ) )
1159 #else // optional_CPP11_OR_GREATER
1162 optional( value_type const & value )
1163 : has_value_( true )
1164 , contained( value )
1167 #endif // optional_CPP11_OR_GREATER
1169 // x.x.3.2, destructor
1175 contained.destruct_value();
1179 // x.x.3.3, assignment
1181 // 1 (C++98and later) - assign explicitly empty
1182 optional & operator=( nullopt_t /*unused*/) optional_noexcept
1188 // 2 (C++98and later) - copy-assign from optional
1189 #if optional_CPP11_OR_GREATER
1190 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1191 optional_REQUIRES_R(
1194 // std::is_copy_constructible<T>::value
1195 // && std::is_copy_assignable<T>::value
1197 operator=( optional const & other )
1199 std11::is_nothrow_move_assignable<T>::value
1200 && std11::is_nothrow_move_constructible<T>::value
1203 optional & operator=( optional const & other )
1206 if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
1207 else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); }
1208 else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; }
1212 #if optional_CPP11_OR_GREATER
1214 // 3 (C++11) - move-assign from optional
1215 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1216 optional_REQUIRES_R(
1219 // std11::is_move_constructible<T>::value
1220 // && std::is_move_assignable<T>::value
1222 operator=( optional && other ) noexcept
1224 if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
1225 else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); }
1226 else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); }
1230 // 4 (C++11) - move-assign from value
1231 template< typename U = T >
1232 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1233 optional_REQUIRES_R(
1235 std::is_constructible<T , U>::value
1236 && std11::is_assignable<T&, U>::value
1237 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1238 && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1239 && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
1241 operator=( U && value )
1245 contained.value() = std::forward<U>( value );
1249 initialize( T( std::forward<U>( value ) ) );
1254 #else // optional_CPP11_OR_GREATER
1256 // 4 (C++98) - copy-assign from value
1257 template< typename U /*= T*/ >
1258 optional & operator=( U const & value )
1260 if ( has_value() ) contained.value() = value;
1261 else initialize( T( value ) );
1265 #endif // optional_CPP11_OR_GREATER
1267 // 5 (C++98 and later) - converting copy-assign from optional
1268 template< typename U >
1269 #if optional_CPP11_OR_GREATER
1270 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1271 optional_REQUIRES_R(
1273 std::is_constructible< T , U const &>::value
1274 && std11::is_assignable< T&, U const &>::value
1275 && !std::is_constructible<T, optional<U> & >::value
1276 && !std::is_constructible<T, optional<U> && >::value
1277 && !std::is_constructible<T, optional<U> const & >::value
1278 && !std::is_constructible<T, optional<U> const && >::value
1279 && !std::is_convertible< optional<U> & , T>::value
1280 && !std::is_convertible< optional<U> && , T>::value
1281 && !std::is_convertible< optional<U> const & , T>::value
1282 && !std::is_convertible< optional<U> const &&, T>::value
1283 && !std11::is_assignable< T&, optional<U> & >::value
1284 && !std11::is_assignable< T&, optional<U> && >::value
1285 && !std11::is_assignable< T&, optional<U> const & >::value
1286 && !std11::is_assignable< T&, optional<U> const && >::value
1290 #endif // optional_CPP11_OR_GREATER
1291 operator=( optional<U> const & other )
1293 return *this = optional( other );
1296 #if optional_CPP11_OR_GREATER
1298 // 6 (C++11) - converting move-assign from optional
1299 template< typename U >
1300 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1301 optional_REQUIRES_R(
1303 std::is_constructible< T , U>::value
1304 && std11::is_assignable< T&, U>::value
1305 && !std::is_constructible<T, optional<U> & >::value
1306 && !std::is_constructible<T, optional<U> && >::value
1307 && !std::is_constructible<T, optional<U> const & >::value
1308 && !std::is_constructible<T, optional<U> const && >::value
1309 && !std::is_convertible< optional<U> & , T>::value
1310 && !std::is_convertible< optional<U> && , T>::value
1311 && !std::is_convertible< optional<U> const & , T>::value
1312 && !std::is_convertible< optional<U> const &&, T>::value
1313 && !std11::is_assignable< T&, optional<U> & >::value
1314 && !std11::is_assignable< T&, optional<U> && >::value
1315 && !std11::is_assignable< T&, optional<U> const & >::value
1316 && !std11::is_assignable< T&, optional<U> const && >::value
1318 operator=( optional<U> && other )
1320 return *this = optional( std::move( other ) );
1323 // 7 (C++11) - emplace
1324 template< typename... Args
1325 optional_REQUIRES_T(
1326 std::is_constructible<T, Args&&...>::value
1329 T& emplace( Args&&... args )
1332 contained.emplace( std::forward<Args>(args)... );
1334 return contained.value();
1337 // 8 (C++11) - emplace, initializer-list
1338 template< typename U, typename... Args
1339 optional_REQUIRES_T(
1340 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1343 T& emplace( std::initializer_list<U> il, Args&&... args )
1346 contained.emplace( il, std::forward<Args>(args)... );
1348 return contained.value();
1351 #endif // optional_CPP11_OR_GREATER
1355 void swap( optional & other )
1356 #if optional_CPP11_OR_GREATER
1358 std11::is_nothrow_move_constructible<T>::value
1359 && std17::is_nothrow_swappable<T>::value
1364 if ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); }
1365 else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); }
1366 else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); }
1369 // x.x.3.5, observers
1371 optional_constexpr value_type const * operator ->() const
1373 return assert( has_value() ),
1374 contained.value_ptr();
1377 optional_constexpr14 value_type * operator ->()
1379 return assert( has_value() ),
1380 contained.value_ptr();
1383 optional_constexpr value_type const & operator *() const optional_ref_qual
1385 return assert( has_value() ),
1389 optional_constexpr14 value_type & operator *() optional_ref_qual
1391 return assert( has_value() ),
1395 #if optional_HAVE( REF_QUALIFIER )
1397 optional_constexpr value_type const && operator *() const optional_refref_qual
1399 return std::move( **this );
1402 optional_constexpr14 value_type && operator *() optional_refref_qual
1404 return std::move( **this );
1409 #if optional_CPP11_OR_GREATER
1410 optional_constexpr explicit operator bool() const optional_noexcept
1415 optional_constexpr operator safe_bool() const optional_noexcept
1417 return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
1421 // NOLINTNEXTLINE( modernize-use-nodiscard )
1422 /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept
1427 // NOLINTNEXTLINE( modernize-use-nodiscard )
1428 /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual
1430 #if optional_CONFIG_NO_EXCEPTIONS
1431 assert( has_value() );
1433 if ( ! has_value() )
1435 throw bad_optional_access();
1438 return contained.value();
1441 optional_constexpr14 value_type & value() optional_ref_qual
1443 #if optional_CONFIG_NO_EXCEPTIONS
1444 assert( has_value() );
1446 if ( ! has_value() )
1448 throw bad_optional_access();
1451 return contained.value();
1454 #if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )
1456 // NOLINTNEXTLINE( modernize-use-nodiscard )
1457 /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual
1459 return std::move( value() );
1462 optional_constexpr14 value_type && value() optional_refref_qual
1464 return std::move( value() );
1469 #if optional_HAVE( REF_QUALIFIER )
1471 template< typename U >
1472 optional_constexpr value_type value_or( U && v ) const optional_ref_qual
1474 return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
1477 template< typename U >
1478 optional_constexpr14 value_type value_or( U && v ) optional_refref_qual
1480 #if optional_COMPILER_CLANG_VERSION
1481 return has_value() ? /*std::move*/( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
1483 return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
1489 template< typename U >
1490 optional_constexpr value_type value_or( U const & v ) const
1492 return has_value() ? contained.value() : static_cast<value_type>( v );
1495 #endif // optional_HAVE( REF_QUALIFIER )
1497 #if !optional_CONFIG_NO_EXTENSIONS
1498 #if optional_HAVE( REF_QUALIFIER )
1500 template< typename F >
1501 optional_constexpr value_type value_or_eval( F f ) const &
1503 return has_value() ? contained.value() : f();
1506 template< typename F >
1507 optional_constexpr14 value_type value_or_eval( F f ) &&
1511 return std::move( contained.value() );
1521 template< typename F >
1522 optional_constexpr value_type value_or_eval( F f ) const
1524 return has_value() ? contained.value() : f();
1527 #endif // optional_HAVE( REF_QUALIFIER )
1528 #endif // !optional_CONFIG_NO_EXTENSIONS
1530 // x.x.3.6, modifiers
1532 void reset() optional_noexcept
1536 contained.destruct_value();
1543 void this_type_does_not_support_comparisons() const {}
1545 template< typename V >
1546 void initialize( V const & value )
1548 assert( ! has_value() );
1549 contained.construct_value( value );
1553 #if optional_CPP11_OR_GREATER
1554 template< typename V >
1555 void initialize( V && value )
1557 assert( ! has_value() );
1558 contained.construct_value( std::forward<V>( value ) );
1566 detail::storage_t< value_type > contained;
1570 // Relational operators
1572 template< typename T, typename U >
1573 optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
1575 return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
1578 template< typename T, typename U >
1579 optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
1584 template< typename T, typename U >
1585 optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
1587 return (!y) ? false : (!x) ? true : *x < *y;
1590 template< typename T, typename U >
1591 optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
1596 template< typename T, typename U >
1597 optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
1602 template< typename T, typename U >
1603 optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
1608 // Comparison with nullopt
1610 template< typename T >
1611 optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1616 template< typename T >
1617 optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1622 template< typename T >
1623 optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1628 template< typename T >
1629 optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1634 template< typename T >
1635 optional_nodiscard optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1640 template< typename T >
1641 optional_nodiscard optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1646 template< typename T >
1647 optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1652 template< typename T >
1653 optional_nodiscard optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1658 template< typename T >
1659 optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1664 template< typename T >
1665 optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1670 template< typename T >
1671 optional_nodiscard optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1676 template< typename T >
1677 optional_nodiscard optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1682 // Comparison with T
1684 template< typename T, typename U >
1685 optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, U const & v )
1687 return bool(x) ? *x == v : false;
1690 template< typename T, typename U >
1691 optional_nodiscard optional_constexpr bool operator==( U const & v, optional<T> const & x )
1693 return bool(x) ? v == *x : false;
1696 template< typename T, typename U >
1697 optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, U const & v )
1699 return bool(x) ? *x != v : true;
1702 template< typename T, typename U >
1703 optional_nodiscard optional_constexpr bool operator!=( U const & v, optional<T> const & x )
1705 return bool(x) ? v != *x : true;
1708 template< typename T, typename U >
1709 optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, U const & v )
1711 return bool(x) ? *x < v : true;
1714 template< typename T, typename U >
1715 optional_nodiscard optional_constexpr bool operator<( U const & v, optional<T> const & x )
1717 return bool(x) ? v < *x : false;
1720 template< typename T, typename U >
1721 optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, U const & v )
1723 return bool(x) ? *x <= v : true;
1726 template< typename T, typename U >
1727 optional_nodiscard optional_constexpr bool operator<=( U const & v, optional<T> const & x )
1729 return bool(x) ? v <= *x : false;
1732 template< typename T, typename U >
1733 optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, U const & v )
1735 return bool(x) ? *x > v : false;
1738 template< typename T, typename U >
1739 optional_nodiscard optional_constexpr bool operator>( U const & v, optional<T> const & x )
1741 return bool(x) ? v > *x : true;
1744 template< typename T, typename U >
1745 optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, U const & v )
1747 return bool(x) ? *x >= v : false;
1750 template< typename T, typename U >
1751 optional_nodiscard optional_constexpr bool operator>=( U const & v, optional<T> const & x )
1753 return bool(x) ? v >= *x : true;
1756 // Specialized algorithms
1758 template< typename T
1759 #if optional_CPP11_OR_GREATER
1760 optional_REQUIRES_T(
1761 std11::is_move_constructible<T>::value
1762 && std17::is_swappable<T>::value )
1765 void swap( optional<T> & x, optional<T> & y )
1766 #if optional_CPP11_OR_GREATER
1767 noexcept( noexcept( x.swap(y) ) )
1773 #if optional_CPP11_OR_GREATER
1775 template< typename T >
1776 optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value )
1778 return optional< typename std::decay<T>::type >( std::forward<T>( value ) );
1781 template< typename T, typename...Args >
1782 optional_constexpr optional<T> make_optional( Args&&... args )
1784 return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
1787 template< typename T, typename U, typename... Args >
1788 optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
1790 return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
1795 template< typename T >
1796 optional<T> make_optional( T const & value )
1798 return optional<T>( value );
1801 #endif // optional_CPP11_OR_GREATER
1803 } // namespace optional_lite
1805 using optional_lite::optional;
1806 using optional_lite::nullopt_t;
1807 using optional_lite::nullopt;
1809 #if ! optional_CONFIG_NO_EXCEPTIONS
1810 using optional_lite::bad_optional_access;
1813 using optional_lite::make_optional;
1815 } // namespace nonstd
1817 #if optional_CPP11_OR_GREATER
1819 // specialize the std::hash algorithm:
1824 struct hash< nonstd::optional<T> >
1827 std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
1829 return bool( v ) ? std::hash<T>{}( *v ) : 0;
1835 #endif // optional_CPP11_OR_GREATER
1837 #if defined(__clang__)
1838 # pragma clang diagnostic pop
1839 #elif defined(__GNUC__)
1840 # pragma GCC diagnostic pop
1841 #elif defined(_MSC_VER )
1842 # pragma warning( pop )
1845 #endif // optional_USES_STD_OPTIONAL
1847 #endif // NONSTD_OPTIONAL_LITE_HPP