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 5
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) || (_HAS_EXCEPTIONS)
60 # define optional_CONFIG_NO_EXCEPTIONS 0
62 # define optional_CONFIG_NO_EXCEPTIONS 1
66 // C++ language version detection (C++20 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 >= 202000L )
84 // C++ language version (represent 98 as 3):
86 #define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
88 // Use C++17 std::optional if available and requested:
90 #if optional_CPP17_OR_GREATER && defined(__has_include )
91 # if __has_include( <optional> )
92 # define optional_HAVE_STD_OPTIONAL 1
94 # define optional_HAVE_STD_OPTIONAL 0
97 # define optional_HAVE_STD_OPTIONAL 0
100 #define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
103 // in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
106 #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
107 #define nonstd_lite_HAVE_IN_PLACE_TYPES 1
109 // C++17 std::in_place in <utility>:
111 #if optional_CPP17_OR_GREATER
118 using std::in_place_type;
119 using std::in_place_index;
120 using std::in_place_t;
121 using std::in_place_type_t;
122 using std::in_place_index_t;
124 #define nonstd_lite_in_place_t( T) std::in_place_t
125 #define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
126 #define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
128 #define nonstd_lite_in_place( T) std::in_place_t{}
129 #define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
130 #define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
132 } // namespace nonstd
134 #else // optional_CPP17_OR_GREATER
142 struct in_place_type_tag {};
144 template< std::size_t K >
145 struct in_place_index_tag {};
147 } // namespace detail
149 struct in_place_t {};
152 inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
157 template< std::size_t K >
158 inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
164 inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
169 template< std::size_t K >
170 inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
175 // mimic templated typedef:
177 #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
178 #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
179 #define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
181 #define nonstd_lite_in_place( T) nonstd::in_place_type<T>
182 #define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
183 #define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
185 } // namespace nonstd
187 #endif // optional_CPP17_OR_GREATER
188 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
191 // Using std::optional:
194 #if optional_USES_STD_OPTIONAL
201 using std::bad_optional_access;
205 using std::nullopt_t;
207 using std::operator==;
208 using std::operator!=;
209 using std::operator<;
210 using std::operator<=;
211 using std::operator>;
212 using std::operator>=;
213 using std::make_optional;
217 #else // optional_USES_STD_OPTIONAL
222 // optional-lite alignment configuration:
224 #ifndef optional_CONFIG_MAX_ALIGN_HACK
225 # define optional_CONFIG_MAX_ALIGN_HACK 0
228 #ifndef optional_CONFIG_ALIGN_AS
229 // no default, used in #if defined()
232 #ifndef optional_CONFIG_ALIGN_AS_FALLBACK
233 # define optional_CONFIG_ALIGN_AS_FALLBACK double
236 // Compiler warning suppression:
238 #if defined(__clang__)
239 # pragma clang diagnostic push
240 # pragma clang diagnostic ignored "-Wundef"
241 #elif defined(__GNUC__)
242 # pragma GCC diagnostic push
243 # pragma GCC diagnostic ignored "-Wundef"
244 #elif defined(_MSC_VER )
245 # pragma warning( push )
248 // half-open range [lo..hi):
249 #define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
251 // Compiler versions:
253 // MSVC++ 6.0 _MSC_VER == 1200 optional_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
254 // MSVC++ 7.0 _MSC_VER == 1300 optional_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
255 // MSVC++ 7.1 _MSC_VER == 1310 optional_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
256 // MSVC++ 8.0 _MSC_VER == 1400 optional_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
257 // MSVC++ 9.0 _MSC_VER == 1500 optional_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
258 // MSVC++ 10.0 _MSC_VER == 1600 optional_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
259 // MSVC++ 11.0 _MSC_VER == 1700 optional_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
260 // MSVC++ 12.0 _MSC_VER == 1800 optional_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
261 // MSVC++ 14.0 _MSC_VER == 1900 optional_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
262 // MSVC++ 14.1 _MSC_VER >= 1910 optional_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
263 // MSVC++ 14.2 _MSC_VER >= 1920 optional_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
265 #if defined(_MSC_VER ) && !defined(__clang__)
266 # define optional_COMPILER_MSVC_VER (_MSC_VER )
267 # define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
269 # define optional_COMPILER_MSVC_VER 0
270 # define optional_COMPILER_MSVC_VERSION 0
273 #define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * (major) + (minor) ) + (patch) )
275 #if defined(__GNUC__) && !defined(__clang__)
276 # define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
278 # define optional_COMPILER_GNUC_VERSION 0
281 #if defined(__clang__)
282 # define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
284 # define optional_COMPILER_CLANG_VERSION 0
287 #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
288 # pragma warning( disable: 4345 ) // initialization behavior changed
291 #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
292 # pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const'
295 // Presence of language and library features:
297 #define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
300 # define optional_HAS_CPP0X _HAS_CPP0X
302 # define optional_HAS_CPP0X 0
305 // Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
307 #if optional_COMPILER_MSVC_VER >= 1900
308 # undef optional_CPP11_OR_GREATER
309 # define optional_CPP11_OR_GREATER 1
312 #define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
313 #define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
314 #define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
315 #define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
316 #define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
317 #define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
319 #define optional_CPP14_000 (optional_CPP14_OR_GREATER)
320 #define optional_CPP17_000 (optional_CPP17_OR_GREATER)
322 // clang >= 2.9, gcc >= 4.9, msvc >= vc14.0/1900 (vs15):
323 #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))
325 // clang >= 3.5, msvc >= vc11 (vs12):
326 #define optional_CPP11_110_C350 ( optional_CPP11_110 && !optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) )
328 // clang >= 3.5, gcc >= 5.0, msvc >= vc11 (vs12):
329 #define optional_CPP11_110_C350_G500 \
330 ( optional_CPP11_110 && \
331 !( optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) \
332 || optional_BETWEEN( optional_COMPILER_GNUC_VERSION , 1, 500 ) ) )
334 // Presence of C++11 language features:
336 #define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
337 #define optional_HAVE_IS_DEFAULT optional_CPP11_140
338 #define optional_HAVE_NOEXCEPT optional_CPP11_140
339 #define optional_HAVE_NULLPTR optional_CPP11_100
340 #define optional_HAVE_REF_QUALIFIER optional_CPP11_140_C290_G490
341 #define optional_HAVE_STATIC_ASSERT optional_CPP11_110
342 #define optional_HAVE_INITIALIZER_LIST optional_CPP11_140
344 // Presence of C++14 language features:
346 #define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
348 // Presence of C++17 language features:
350 #define optional_HAVE_NODISCARD optional_CPP17_000
352 // Presence of C++ library features:
354 #define optional_HAVE_CONDITIONAL optional_CPP11_120
355 #define optional_HAVE_REMOVE_CV optional_CPP11_120
356 #define optional_HAVE_TYPE_TRAITS optional_CPP11_90
358 #define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
359 #define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )
361 #define optional_HAVE_IS_ASSIGNABLE optional_CPP11_110_C350
362 #define optional_HAVE_IS_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350
363 #define optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE optional_CPP11_110_C350
364 #define optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350
365 #define optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE optional_CPP11_110_C350_G500
366 #define optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350_G500
368 // C++ feature usage:
370 #if optional_HAVE( CONSTEXPR_11 )
371 # define optional_constexpr constexpr
373 # define optional_constexpr /*constexpr*/
376 #if optional_HAVE( IS_DEFAULT )
377 # define optional_is_default = default;
379 # define optional_is_default {}
382 #if optional_HAVE( CONSTEXPR_14 )
383 # define optional_constexpr14 constexpr
385 # define optional_constexpr14 /*constexpr*/
388 #if optional_HAVE( NODISCARD )
389 # define optional_nodiscard [[nodiscard]]
391 # define optional_nodiscard /*[[nodiscard]]*/
394 #if optional_HAVE( NOEXCEPT )
395 # define optional_noexcept noexcept
397 # define optional_noexcept /*noexcept*/
400 #if optional_HAVE( NULLPTR )
401 # define optional_nullptr nullptr
403 # define optional_nullptr NULL
406 #if optional_HAVE( REF_QUALIFIER )
407 // NOLINTNEXTLINE( bugprone-macro-parentheses )
408 # define optional_ref_qual &
409 # define optional_refref_qual &&
411 # define optional_ref_qual /*&*/
412 # define optional_refref_qual /*&&*/
415 #if optional_HAVE( STATIC_ASSERT )
416 # define optional_static_assert(expr, text) static_assert(expr, text);
418 # define optional_static_assert(expr, text) /*static_assert(expr, text);*/
421 // additional includes:
423 #if optional_CONFIG_NO_EXCEPTIONS
424 // already included: <cassert>
426 # include <stdexcept>
429 #if optional_CPP11_OR_GREATER
430 # include <functional>
433 #if optional_HAVE( INITIALIZER_LIST )
434 # include <initializer_list>
437 #if optional_HAVE( TYPE_TRAITS )
438 # include <type_traits>
439 #elif optional_HAVE( TR1_TYPE_TRAITS )
440 # include <tr1/type_traits>
445 #if optional_CPP11_OR_GREATER
447 #define optional_REQUIRES_0(...) \
448 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
450 #define optional_REQUIRES_T(...) \
451 , typename std::enable_if< (__VA_ARGS__), int >::type = 0
453 #define optional_REQUIRES_R(R, ...) \
454 typename std::enable_if< (__VA_ARGS__), R>::type
456 #define optional_REQUIRES_A(...) \
457 , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
465 namespace nonstd { namespace optional_lite {
469 template< class T, T v > struct integral_constant { enum { value = v }; };
470 template< bool B > struct bool_constant : integral_constant<bool, B>{};
472 typedef bool_constant< true > true_type;
473 typedef bool_constant< false > false_type;
475 #if optional_CPP11_OR_GREATER
478 template< typename T > T & move( T & t ) { return t; }
481 #if optional_HAVE( CONDITIONAL )
482 using std::conditional;
484 template< bool B, typename T, typename F > struct conditional { typedef T type; };
485 template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
486 #endif // optional_HAVE_CONDITIONAL
488 #if optional_HAVE( IS_ASSIGNABLE )
489 using std::is_assignable;
491 template< class T, class U > struct is_assignable : std11::true_type{};
494 #if optional_HAVE( IS_MOVE_CONSTRUCTIBLE )
495 using std::is_move_constructible;
497 template< class T > struct is_move_constructible : std11::true_type{};
500 #if optional_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE )
501 using std::is_nothrow_move_assignable;
503 template< class T > struct is_nothrow_move_assignable : std11::true_type{};
506 #if optional_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE )
507 using std::is_nothrow_move_constructible;
509 template< class T > struct is_nothrow_move_constructible : std11::true_type{};
512 #if optional_HAVE( IS_TRIVIALLY_COPY_CONSTRUCTIBLE )
513 using std::is_trivially_copy_constructible;
515 template< class T > struct is_trivially_copy_constructible : std11::true_type{};
518 #if optional_HAVE( IS_TRIVIALLY_MOVE_CONSTRUCTIBLE )
519 using std::is_trivially_move_constructible;
521 template< class T > struct is_trivially_move_constructible : std11::true_type{};
526 #if optional_CPP11_OR_GREATER
528 /// type traits C++17:
532 #if optional_CPP17_OR_GREATER
534 using std::is_swappable;
535 using std::is_nothrow_swappable;
537 #elif optional_CPP11_OR_GREATER
545 template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
546 static std11::true_type test( int /*unused*/ );
549 static std11::false_type test(...);
552 struct is_nothrow_swappable
554 // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
556 template< typename T >
557 static constexpr bool satisfies()
559 return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
562 template< typename T >
563 static auto test( int /*unused*/ ) -> std11::integral_constant<bool, satisfies<T>()>{}
566 static auto test(...) -> std11::false_type;
569 } // namespace detail
571 // is [nothow] swappable:
573 template< typename T >
574 struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
576 template< typename T >
577 struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
579 #endif // optional_CPP17_OR_GREATER
583 /// type traits C++20:
587 template< typename T >
590 typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
595 #endif // optional_CPP11_OR_GREATER
599 template< typename T >
608 template< typename Head, typename Tail >
615 #if optional_CONFIG_MAX_ALIGN_HACK
617 // Max align, use most restricted type for alignment:
619 #define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ )
620 #define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
621 #define optional_UNIQUE3( name, line ) name ## line
623 #define optional_ALIGN_TYPE( type ) \
624 type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
626 template< typename T >
627 struct struct_t { T _; };
631 optional_ALIGN_TYPE( char );
632 optional_ALIGN_TYPE( short int );
633 optional_ALIGN_TYPE( int );
634 optional_ALIGN_TYPE( long int );
635 optional_ALIGN_TYPE( float );
636 optional_ALIGN_TYPE( double );
637 optional_ALIGN_TYPE( long double );
638 optional_ALIGN_TYPE( char * );
639 optional_ALIGN_TYPE( short int * );
640 optional_ALIGN_TYPE( int * );
641 optional_ALIGN_TYPE( long int * );
642 optional_ALIGN_TYPE( float * );
643 optional_ALIGN_TYPE( double * );
644 optional_ALIGN_TYPE( long double * );
645 optional_ALIGN_TYPE( void * );
647 #ifdef HAVE_LONG_LONG
648 optional_ALIGN_TYPE( long long );
653 Unknown ( * optional_UNIQUE(_) )( Unknown );
654 Unknown * Unknown::* optional_UNIQUE(_);
655 Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
657 struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_);
658 struct_t< Unknown * Unknown::* > optional_UNIQUE(_);
659 struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
662 #undef optional_UNIQUE
663 #undef optional_UNIQUE2
664 #undef optional_UNIQUE3
666 #undef optional_ALIGN_TYPE
668 #elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
670 // Use user-specified type for alignment:
672 #define optional_ALIGN_AS( unused ) \
673 optional_CONFIG_ALIGN_AS
675 #else // optional_CONFIG_MAX_ALIGN_HACK
677 // Determine POD type to use for alignment:
679 #define optional_ALIGN_AS( to_align ) \
680 typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
682 template< typename T >
685 template< typename T >
686 struct alignment_of_hack
693 template< size_t A, size_t S >
694 struct alignment_logic
696 enum { value = A < S ? A : S };
699 template< typename T >
702 enum { value = alignment_logic<
703 sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
706 template< typename List, size_t N >
709 typedef typename std11::conditional<
710 N == sizeof( typename List::head ),
712 typename type_of_size<typename List::tail, N >::type >::type type;
716 struct type_of_size< nulltype, N >
718 typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
721 template< typename T>
722 struct struct_t { T _; };
724 #define optional_ALIGN_TYPE( type ) \
725 typelist< type , typelist< struct_t< type >
730 optional_ALIGN_TYPE( char ),
731 optional_ALIGN_TYPE( short ),
732 optional_ALIGN_TYPE( int ),
733 optional_ALIGN_TYPE( long ),
734 optional_ALIGN_TYPE( float ),
735 optional_ALIGN_TYPE( double ),
736 optional_ALIGN_TYPE( long double ),
738 optional_ALIGN_TYPE( char *),
739 optional_ALIGN_TYPE( short * ),
740 optional_ALIGN_TYPE( int * ),
741 optional_ALIGN_TYPE( long * ),
742 optional_ALIGN_TYPE( float * ),
743 optional_ALIGN_TYPE( double * ),
744 optional_ALIGN_TYPE( long double * ),
746 optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
747 optional_ALIGN_TYPE( Unknown * Unknown::* ),
748 optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
751 > > > > > > > > > > > > > >
752 > > > > > > > > > > > > > >
756 #undef optional_ALIGN_TYPE
758 #endif // optional_CONFIG_MAX_ALIGN_HACK
760 /// C++03 constructed union to hold value.
762 template< typename T >
766 // template< typename > friend class optional;
768 typedef T value_type;
770 storage_t() optional_is_default
772 explicit storage_t( value_type const & v )
774 construct_value( v );
777 void construct_value( value_type const & v )
779 ::new( value_ptr() ) value_type( v );
782 #if optional_CPP11_OR_GREATER
784 explicit storage_t( value_type && v )
786 construct_value( std::move( v ) );
789 void construct_value( value_type && v )
791 ::new( value_ptr() ) value_type( std::move( v ) );
794 template< class... Args >
795 storage_t( nonstd_lite_in_place_t(T), Args&&... args )
797 emplace( std::forward<Args>(args)... );
800 template< class... Args >
801 void emplace( Args&&... args )
803 ::new( value_ptr() ) value_type( std::forward<Args>(args)... );
806 template< class U, class... Args >
807 void emplace( std::initializer_list<U> il, Args&&... args )
809 ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... );
814 void destruct_value()
819 optional_nodiscard value_type const * value_ptr() const
821 return as<value_type>();
824 value_type * value_ptr()
826 return as<value_type>();
829 optional_nodiscard value_type const & value() const optional_ref_qual
831 return * value_ptr();
834 value_type & value() optional_ref_qual
836 return * value_ptr();
839 #if optional_HAVE( REF_QUALIFIER )
841 optional_nodiscard value_type const && value() const optional_refref_qual
843 return std::move( value() );
846 value_type && value() optional_refref_qual
848 return std::move( value() );
853 #if optional_CPP11_OR_GREATER
855 using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
856 aligned_storage_t data;
858 #elif optional_CONFIG_MAX_ALIGN_HACK
860 typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
863 aligned_storage_t data;
866 typedef optional_ALIGN_AS(value_type) align_as_type;
868 typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
869 aligned_storage_t data;
871 # undef optional_ALIGN_AS
873 #endif // optional_CONFIG_MAX_ALIGN_HACK
875 optional_nodiscard void * ptr() optional_noexcept
880 optional_nodiscard void const * ptr() const optional_noexcept
885 template <typename U>
886 optional_nodiscard U * as()
888 return reinterpret_cast<U*>( ptr() );
891 template <typename U>
892 optional_nodiscard U const * as() const
894 return reinterpret_cast<U const *>( ptr() );
898 } // namespace detail
900 /// disengaged state tag
905 explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
908 #if optional_HAVE( CONSTEXPR_11 )
909 constexpr nullopt_t nullopt{ nullopt_t::init{} };
911 // extra parenthesis to prevent the most vexing parse:
912 const nullopt_t nullopt(( nullopt_t::init() ));
915 /// optional access error
917 #if ! optional_CONFIG_NO_EXCEPTIONS
919 class bad_optional_access : public std::logic_error
922 explicit bad_optional_access()
923 : logic_error( "bad optional access" ) {}
926 #endif //optional_CONFIG_NO_EXCEPTIONS
930 template< typename T>
933 optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, nullopt_t>::value ),
934 "T in optional<T> must not be of type 'nullopt_t'.")
936 optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, in_place_t>::value ),
937 "T in optional<T> must not be of type 'in_place_t'.")
939 optional_static_assert(( std::is_object<T>::value && std::is_destructible<T>::value && !std::is_array<T>::value ),
940 "T in optional<T> must meet the Cpp17Destructible requirements.")
943 template< typename > friend class optional;
945 typedef void (optional::*safe_bool)() const;
948 typedef T value_type;
950 // x.x.3.1, constructors
952 // 1a - default construct
953 optional_constexpr optional() optional_noexcept
954 : has_value_( false )
958 // 1b - construct explicitly empty
959 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
960 optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept
961 : has_value_( false )
965 // 2 - copy-construct
966 #if optional_CPP11_OR_GREATER
967 // template< typename U = T
968 // optional_REQUIRES_T(
969 // std::is_copy_constructible<U>::value
970 // || std11::is_trivially_copy_constructible<U>::value
974 optional_constexpr14 optional( optional const & other )
975 : has_value_( other.has_value() )
977 if ( other.has_value() )
979 contained.construct_value( other.contained.value() );
983 #if optional_CPP11_OR_GREATER
985 // 3 (C++11) - move-construct from optional
986 template< typename U = T
988 std11::is_move_constructible<U>::value
989 || std11::is_trivially_move_constructible<U>::value
992 optional_constexpr14 optional( optional && other )
993 // NOLINTNEXTLINE( performance-noexcept-move-constructor )
994 noexcept( std11::is_nothrow_move_constructible<T>::value )
995 : has_value_( other.has_value() )
997 if ( other.has_value() )
999 contained.construct_value( std::move( other.contained.value() ) );
1003 // 4a (C++11) - explicit converting copy-construct from optional
1004 template< typename U
1005 optional_REQUIRES_T(
1006 std::is_constructible<T, U const &>::value
1007 && !std::is_constructible<T, optional<U> & >::value
1008 && !std::is_constructible<T, optional<U> && >::value
1009 && !std::is_constructible<T, optional<U> const & >::value
1010 && !std::is_constructible<T, optional<U> const && >::value
1011 && !std::is_convertible< optional<U> & , T>::value
1012 && !std::is_convertible< optional<U> && , T>::value
1013 && !std::is_convertible< optional<U> const & , T>::value
1014 && !std::is_convertible< optional<U> const &&, T>::value
1015 && !std::is_convertible< U const & , T>::value /*=> explicit */
1018 explicit optional( optional<U> const & other )
1019 : has_value_( other.has_value() )
1021 if ( other.has_value() )
1023 contained.construct_value( T{ other.contained.value() } );
1026 #endif // optional_CPP11_OR_GREATER
1028 // 4b (C++98 and later) - non-explicit converting copy-construct from optional
1029 template< typename U
1030 #if optional_CPP11_OR_GREATER
1031 optional_REQUIRES_T(
1032 std::is_constructible<T, U const &>::value
1033 && !std::is_constructible<T, optional<U> & >::value
1034 && !std::is_constructible<T, optional<U> && >::value
1035 && !std::is_constructible<T, optional<U> const & >::value
1036 && !std::is_constructible<T, optional<U> const && >::value
1037 && !std::is_convertible< optional<U> & , T>::value
1038 && !std::is_convertible< optional<U> && , T>::value
1039 && !std::is_convertible< optional<U> const & , T>::value
1040 && !std::is_convertible< optional<U> const &&, T>::value
1041 && std::is_convertible< U const & , T>::value /*=> non-explicit */
1043 #endif // optional_CPP11_OR_GREATER
1045 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1046 /*non-explicit*/ optional( optional<U> const & other )
1047 : has_value_( other.has_value() )
1049 if ( other.has_value() )
1051 contained.construct_value( other.contained.value() );
1055 #if optional_CPP11_OR_GREATER
1057 // 5a (C++11) - explicit converting move-construct from optional
1058 template< typename U
1059 optional_REQUIRES_T(
1060 std::is_constructible<T, U &&>::value
1061 && !std::is_constructible<T, optional<U> & >::value
1062 && !std::is_constructible<T, optional<U> && >::value
1063 && !std::is_constructible<T, optional<U> const & >::value
1064 && !std::is_constructible<T, optional<U> const && >::value
1065 && !std::is_convertible< optional<U> & , T>::value
1066 && !std::is_convertible< optional<U> && , T>::value
1067 && !std::is_convertible< optional<U> const & , T>::value
1068 && !std::is_convertible< optional<U> const &&, T>::value
1069 && !std::is_convertible< U &&, T>::value /*=> explicit */
1072 explicit optional( optional<U> && other
1074 : has_value_( other.has_value() )
1076 if ( other.has_value() )
1078 contained.construct_value( T{ std::move( other.contained.value() ) } );
1082 // 5a (C++11) - non-explicit converting move-construct from optional
1083 template< typename U
1084 optional_REQUIRES_T(
1085 std::is_constructible<T, U &&>::value
1086 && !std::is_constructible<T, optional<U> & >::value
1087 && !std::is_constructible<T, optional<U> && >::value
1088 && !std::is_constructible<T, optional<U> const & >::value
1089 && !std::is_constructible<T, optional<U> const && >::value
1090 && !std::is_convertible< optional<U> & , T>::value
1091 && !std::is_convertible< optional<U> && , T>::value
1092 && !std::is_convertible< optional<U> const & , T>::value
1093 && !std::is_convertible< optional<U> const &&, T>::value
1094 && std::is_convertible< U &&, T>::value /*=> non-explicit */
1097 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1098 /*non-explicit*/ optional( optional<U> && other )
1099 : has_value_( other.has_value() )
1101 if ( other.has_value() )
1103 contained.construct_value( std::move( other.contained.value() ) );
1107 // 6 (C++11) - in-place construct
1108 template< typename... Args
1109 optional_REQUIRES_T(
1110 std::is_constructible<T, Args&&...>::value
1113 optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
1114 : has_value_( true )
1115 , contained( in_place, std::forward<Args>(args)... )
1118 // 7 (C++11) - in-place construct, initializer-list
1119 template< typename U, typename... Args
1120 optional_REQUIRES_T(
1121 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1124 optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
1125 : has_value_( true )
1126 , contained( T( il, std::forward<Args>(args)...) )
1129 // 8a (C++11) - explicit move construct from value
1130 template< typename U = T
1131 optional_REQUIRES_T(
1132 std::is_constructible<T, U&&>::value
1133 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1134 && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1135 && !std::is_convertible<U&&, T>::value /*=> explicit */
1138 optional_constexpr explicit optional( U && value )
1139 : has_value_( true )
1140 , contained( nonstd_lite_in_place(T), std::forward<U>( value ) )
1143 // 8b (C++11) - non-explicit move construct from value
1144 template< typename U = T
1145 optional_REQUIRES_T(
1146 std::is_constructible<T, U&&>::value
1147 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1148 && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1149 && std::is_convertible<U&&, T>::value /*=> non-explicit */
1152 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1153 optional_constexpr /*non-explicit*/ optional( U && value )
1154 : has_value_( true )
1155 , contained( nonstd_lite_in_place(T), std::forward<U>( value ) )
1158 #else // optional_CPP11_OR_GREATER
1161 optional( value_type const & value )
1162 : has_value_( true )
1163 , contained( value )
1166 #endif // optional_CPP11_OR_GREATER
1168 // x.x.3.2, destructor
1174 contained.destruct_value();
1178 // x.x.3.3, assignment
1180 // 1 (C++98and later) - assign explicitly empty
1181 optional & operator=( nullopt_t /*unused*/) optional_noexcept
1187 // 2 (C++98and later) - copy-assign from optional
1188 #if optional_CPP11_OR_GREATER
1189 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1190 optional_REQUIRES_R(
1193 // std::is_copy_constructible<T>::value
1194 // && std::is_copy_assignable<T>::value
1196 operator=( optional const & other )
1198 std11::is_nothrow_move_assignable<T>::value
1199 && std11::is_nothrow_move_constructible<T>::value
1202 optional & operator=( optional const & other )
1205 if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
1206 else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); }
1207 else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; }
1211 #if optional_CPP11_OR_GREATER
1213 // 3 (C++11) - move-assign from optional
1214 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1215 optional_REQUIRES_R(
1218 // std11::is_move_constructible<T>::value
1219 // && std::is_move_assignable<T>::value
1221 operator=( optional && other ) noexcept
1223 if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
1224 else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); }
1225 else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); }
1229 // 4 (C++11) - move-assign from value
1230 template< typename U = T >
1231 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1232 optional_REQUIRES_R(
1234 std::is_constructible<T , U>::value
1235 && std11::is_assignable<T&, U>::value
1236 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1237 && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1238 && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
1240 operator=( U && value )
1244 contained.value() = std::forward<U>( value );
1248 initialize( T( std::forward<U>( value ) ) );
1253 #else // optional_CPP11_OR_GREATER
1255 // 4 (C++98) - copy-assign from value
1256 template< typename U /*= T*/ >
1257 optional & operator=( U const & value )
1259 if ( has_value() ) contained.value() = value;
1260 else initialize( T( value ) );
1264 #endif // optional_CPP11_OR_GREATER
1266 // 5 (C++98 and later) - converting copy-assign from optional
1267 template< typename U >
1268 #if optional_CPP11_OR_GREATER
1269 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1270 optional_REQUIRES_R(
1272 std::is_constructible< T , U const &>::value
1273 && std11::is_assignable< T&, U const &>::value
1274 && !std::is_constructible<T, optional<U> & >::value
1275 && !std::is_constructible<T, optional<U> && >::value
1276 && !std::is_constructible<T, optional<U> const & >::value
1277 && !std::is_constructible<T, optional<U> const && >::value
1278 && !std::is_convertible< optional<U> & , T>::value
1279 && !std::is_convertible< optional<U> && , T>::value
1280 && !std::is_convertible< optional<U> const & , T>::value
1281 && !std::is_convertible< optional<U> const &&, T>::value
1282 && !std11::is_assignable< T&, optional<U> & >::value
1283 && !std11::is_assignable< T&, optional<U> && >::value
1284 && !std11::is_assignable< T&, optional<U> const & >::value
1285 && !std11::is_assignable< T&, optional<U> const && >::value
1289 #endif // optional_CPP11_OR_GREATER
1290 operator=( optional<U> const & other )
1292 return *this = optional( other );
1295 #if optional_CPP11_OR_GREATER
1297 // 6 (C++11) - converting move-assign from optional
1298 template< typename U >
1299 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1300 optional_REQUIRES_R(
1302 std::is_constructible< T , U>::value
1303 && std11::is_assignable< T&, U>::value
1304 && !std::is_constructible<T, optional<U> & >::value
1305 && !std::is_constructible<T, optional<U> && >::value
1306 && !std::is_constructible<T, optional<U> const & >::value
1307 && !std::is_constructible<T, optional<U> const && >::value
1308 && !std::is_convertible< optional<U> & , T>::value
1309 && !std::is_convertible< optional<U> && , T>::value
1310 && !std::is_convertible< optional<U> const & , T>::value
1311 && !std::is_convertible< optional<U> const &&, T>::value
1312 && !std11::is_assignable< T&, optional<U> & >::value
1313 && !std11::is_assignable< T&, optional<U> && >::value
1314 && !std11::is_assignable< T&, optional<U> const & >::value
1315 && !std11::is_assignable< T&, optional<U> const && >::value
1317 operator=( optional<U> && other )
1319 return *this = optional( std::move( other ) );
1322 // 7 (C++11) - emplace
1323 template< typename... Args
1324 optional_REQUIRES_T(
1325 std::is_constructible<T, Args&&...>::value
1328 T& emplace( Args&&... args )
1331 contained.emplace( std::forward<Args>(args)... );
1333 return contained.value();
1336 // 8 (C++11) - emplace, initializer-list
1337 template< typename U, typename... Args
1338 optional_REQUIRES_T(
1339 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1342 T& emplace( std::initializer_list<U> il, Args&&... args )
1345 contained.emplace( il, std::forward<Args>(args)... );
1347 return contained.value();
1350 #endif // optional_CPP11_OR_GREATER
1354 void swap( optional & other )
1355 #if optional_CPP11_OR_GREATER
1357 std11::is_nothrow_move_constructible<T>::value
1358 && std17::is_nothrow_swappable<T>::value
1363 if ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); }
1364 else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); }
1365 else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); }
1368 // x.x.3.5, observers
1370 optional_constexpr value_type const * operator ->() const
1372 return assert( has_value() ),
1373 contained.value_ptr();
1376 optional_constexpr14 value_type * operator ->()
1378 return assert( has_value() ),
1379 contained.value_ptr();
1382 optional_constexpr value_type const & operator *() const optional_ref_qual
1384 return assert( has_value() ),
1388 optional_constexpr14 value_type & operator *() optional_ref_qual
1390 return assert( has_value() ),
1394 #if optional_HAVE( REF_QUALIFIER )
1396 optional_constexpr value_type const && operator *() const optional_refref_qual
1398 return std::move( **this );
1401 optional_constexpr14 value_type && operator *() optional_refref_qual
1403 return std::move( **this );
1408 #if optional_CPP11_OR_GREATER
1409 optional_constexpr explicit operator bool() const optional_noexcept
1414 optional_constexpr operator safe_bool() const optional_noexcept
1416 return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
1420 // NOLINTNEXTLINE( modernize-use-nodiscard )
1421 /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept
1426 // NOLINTNEXTLINE( modernize-use-nodiscard )
1427 /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual
1429 #if optional_CONFIG_NO_EXCEPTIONS
1430 assert( has_value() );
1432 if ( ! has_value() )
1434 throw bad_optional_access();
1437 return contained.value();
1440 optional_constexpr14 value_type & value() optional_ref_qual
1442 #if optional_CONFIG_NO_EXCEPTIONS
1443 assert( has_value() );
1445 if ( ! has_value() )
1447 throw bad_optional_access();
1450 return contained.value();
1453 #if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )
1455 // NOLINTNEXTLINE( modernize-use-nodiscard )
1456 /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual
1458 return std::move( value() );
1461 optional_constexpr14 value_type && value() optional_refref_qual
1463 return std::move( value() );
1468 #if optional_HAVE( REF_QUALIFIER )
1470 template< typename U >
1471 optional_constexpr value_type value_or( U && v ) const optional_ref_qual
1473 return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
1476 template< typename U >
1477 optional_constexpr14 value_type value_or( U && v ) optional_refref_qual
1479 #if optional_COMPILER_CLANG_VERSION
1480 return has_value() ? /*std::move*/( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
1482 return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
1488 template< typename U >
1489 optional_constexpr value_type value_or( U const & v ) const
1491 return has_value() ? contained.value() : static_cast<value_type>( v );
1494 #endif // optional_HAVE( REF_QUALIFIER )
1496 #if !optional_CONFIG_NO_EXTENSIONS
1497 #if optional_HAVE( REF_QUALIFIER )
1499 template< typename F >
1500 optional_constexpr value_type value_or_eval( F f ) const &
1502 return has_value() ? contained.value() : f();
1505 template< typename F >
1506 optional_constexpr14 value_type value_or_eval( F f ) &&
1510 return std::move( contained.value() );
1520 template< typename F >
1521 optional_constexpr value_type value_or_eval( F f ) const
1523 return has_value() ? contained.value() : f();
1526 #endif // optional_HAVE( REF_QUALIFIER )
1527 #endif // !optional_CONFIG_NO_EXTENSIONS
1529 // x.x.3.6, modifiers
1531 void reset() optional_noexcept
1535 contained.destruct_value();
1542 void this_type_does_not_support_comparisons() const {}
1544 template< typename V >
1545 void initialize( V const & value )
1547 assert( ! has_value() );
1548 contained.construct_value( value );
1552 #if optional_CPP11_OR_GREATER
1553 template< typename V >
1554 void initialize( V && value )
1556 assert( ! has_value() );
1557 contained.construct_value( std::move( value ) );
1565 detail::storage_t< value_type > contained;
1569 // Relational operators
1571 template< typename T, typename U >
1572 optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
1574 return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
1577 template< typename T, typename U >
1578 optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
1583 template< typename T, typename U >
1584 optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
1586 return (!y) ? false : (!x) ? true : *x < *y;
1589 template< typename T, typename U >
1590 optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
1595 template< typename T, typename U >
1596 optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
1601 template< typename T, typename U >
1602 optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
1607 // Comparison with nullopt
1609 template< typename T >
1610 optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1615 template< typename T >
1616 optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1621 template< typename T >
1622 optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1627 template< typename T >
1628 optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1633 template< typename T >
1634 optional_nodiscard optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1639 template< typename T >
1640 optional_nodiscard optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1645 template< typename T >
1646 optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1651 template< typename T >
1652 optional_nodiscard optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1657 template< typename T >
1658 optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1663 template< typename T >
1664 optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1669 template< typename T >
1670 optional_nodiscard optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1675 template< typename T >
1676 optional_nodiscard optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1681 // Comparison with T
1683 template< typename T, typename U >
1684 optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, U const & v )
1686 return bool(x) ? *x == v : false;
1689 template< typename T, typename U >
1690 optional_nodiscard optional_constexpr bool operator==( U const & v, optional<T> const & x )
1692 return bool(x) ? v == *x : false;
1695 template< typename T, typename U >
1696 optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, U const & v )
1698 return bool(x) ? *x != v : true;
1701 template< typename T, typename U >
1702 optional_nodiscard optional_constexpr bool operator!=( U const & v, optional<T> const & x )
1704 return bool(x) ? v != *x : true;
1707 template< typename T, typename U >
1708 optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, U const & v )
1710 return bool(x) ? *x < v : true;
1713 template< typename T, typename U >
1714 optional_nodiscard optional_constexpr bool operator<( U const & v, optional<T> const & x )
1716 return bool(x) ? v < *x : false;
1719 template< typename T, typename U >
1720 optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, U const & v )
1722 return bool(x) ? *x <= v : true;
1725 template< typename T, typename U >
1726 optional_nodiscard optional_constexpr bool operator<=( U const & v, optional<T> const & x )
1728 return bool(x) ? v <= *x : false;
1731 template< typename T, typename U >
1732 optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, U const & v )
1734 return bool(x) ? *x > v : false;
1737 template< typename T, typename U >
1738 optional_nodiscard optional_constexpr bool operator>( U const & v, optional<T> const & x )
1740 return bool(x) ? v > *x : true;
1743 template< typename T, typename U >
1744 optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, U const & v )
1746 return bool(x) ? *x >= v : false;
1749 template< typename T, typename U >
1750 optional_nodiscard optional_constexpr bool operator>=( U const & v, optional<T> const & x )
1752 return bool(x) ? v >= *x : true;
1755 // Specialized algorithms
1757 template< typename T
1758 #if optional_CPP11_OR_GREATER
1759 optional_REQUIRES_T(
1760 std11::is_move_constructible<T>::value
1761 && std17::is_swappable<T>::value )
1764 void swap( optional<T> & x, optional<T> & y )
1765 #if optional_CPP11_OR_GREATER
1766 noexcept( noexcept( x.swap(y) ) )
1772 #if optional_CPP11_OR_GREATER
1774 template< typename T >
1775 optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value )
1777 return optional< typename std::decay<T>::type >( std::forward<T>( value ) );
1780 template< typename T, typename...Args >
1781 optional_constexpr optional<T> make_optional( Args&&... args )
1783 return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
1786 template< typename T, typename U, typename... Args >
1787 optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
1789 return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
1794 template< typename T >
1795 optional<T> make_optional( T const & value )
1797 return optional<T>( value );
1800 #endif // optional_CPP11_OR_GREATER
1802 } // namespace optional_lite
1804 using optional_lite::optional;
1805 using optional_lite::nullopt_t;
1806 using optional_lite::nullopt;
1808 #if ! optional_CONFIG_NO_EXCEPTIONS
1809 using optional_lite::bad_optional_access;
1812 using optional_lite::make_optional;
1814 } // namespace nonstd
1816 #if optional_CPP11_OR_GREATER
1818 // specialize the std::hash algorithm:
1823 struct hash< nonstd::optional<T> >
1826 std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
1828 return bool( v ) ? std::hash<T>{}( *v ) : 0;
1834 #endif // optional_CPP11_OR_GREATER
1836 #if defined(__clang__)
1837 # pragma clang diagnostic pop
1838 #elif defined(__GNUC__)
1839 # pragma GCC diagnostic pop
1840 #elif defined(_MSC_VER )
1841 # pragma warning( pop )
1844 #endif // optional_USES_STD_OPTIONAL
1846 #endif // NONSTD_OPTIONAL_LITE_HPP