]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/arrow/vendored/optional.hpp
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / arrow / vendored / optional.hpp
CommitLineData
1d09f67e
TL
1// Vendored from git tag v3.2.0
2
3// Copyright (c) 2014-2018 Martin Moene
4//
5// https://github.com/martinmoene/optional-lite
6//
7// Distributed under the Boost Software License, Version 1.0.
8// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10#pragma once
11
12#ifndef NONSTD_OPTIONAL_LITE_HPP
13#define NONSTD_OPTIONAL_LITE_HPP
14
15#define optional_lite_MAJOR 3
16#define optional_lite_MINOR 2
17#define optional_lite_PATCH 0
18
19#define optional_lite_VERSION optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH)
20
21#define optional_STRINGIFY( x ) optional_STRINGIFY_( x )
22#define optional_STRINGIFY_( x ) #x
23
24// optional-lite configuration:
25
26#define optional_OPTIONAL_DEFAULT 0
27#define optional_OPTIONAL_NONSTD 1
28#define optional_OPTIONAL_STD 2
29
30#if !defined( optional_CONFIG_SELECT_OPTIONAL )
31# define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
32#endif
33
34// Control presence of exception handling (try and auto discover):
35
36#ifndef optional_CONFIG_NO_EXCEPTIONS
37# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
38# define optional_CONFIG_NO_EXCEPTIONS 0
39# else
40# define optional_CONFIG_NO_EXCEPTIONS 1
41# endif
42#endif
43
44// C++ language version detection (C++20 is speculative):
45// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
46
47#ifndef optional_CPLUSPLUS
48# if defined(_MSVC_LANG ) && !defined(__clang__)
49# define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
50# else
51# define optional_CPLUSPLUS __cplusplus
52# endif
53#endif
54
55#define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L )
56#define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L )
57#define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L )
58#define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L )
59#define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L )
60#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L )
61
62// C++ language version (represent 98 as 3):
63
64#define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
65
66// Use C++17 std::optional if available and requested:
67
68#if optional_CPP17_OR_GREATER && defined(__has_include )
69# if __has_include( <optional> )
70# define optional_HAVE_STD_OPTIONAL 1
71# else
72# define optional_HAVE_STD_OPTIONAL 0
73# endif
74#else
75# define optional_HAVE_STD_OPTIONAL 0
76#endif
77
78#define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
79
80//
81// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
82//
83
84#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
85#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
86
87// C++17 std::in_place in <utility>:
88
89#if optional_CPP17_OR_GREATER
90
91#include <utility>
92
93namespace nonstd {
94
95using std::in_place;
96using std::in_place_type;
97using std::in_place_index;
98using std::in_place_t;
99using std::in_place_type_t;
100using std::in_place_index_t;
101
102#define nonstd_lite_in_place_t( T) std::in_place_t
103#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
104#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
105
106#define nonstd_lite_in_place( T) std::in_place_t{}
107#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
108#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
109
110} // namespace nonstd
111
112#else // optional_CPP17_OR_GREATER
113
114#include <cstddef>
115
116namespace nonstd {
117namespace detail {
118
119template< class T >
120struct in_place_type_tag {};
121
122template< std::size_t K >
123struct in_place_index_tag {};
124
125} // namespace detail
126
127struct in_place_t {};
128
129template< class T >
130inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
131{
132 return in_place_t();
133}
134
135template< std::size_t K >
136inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
137{
138 return in_place_t();
139}
140
141template< class T >
142inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
143{
144 return in_place_t();
145}
146
147template< std::size_t K >
148inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
149{
150 return in_place_t();
151}
152
153// mimic templated typedef:
154
155#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
156#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
157#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
158
159#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
160#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
161#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
162
163} // namespace nonstd
164
165#endif // optional_CPP17_OR_GREATER
166#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
167
168//
169// Using std::optional:
170//
171
172#if optional_USES_STD_OPTIONAL
173
174#include <optional>
175
176namespace nonstd {
177
178 using std::optional;
179 using std::bad_optional_access;
180 using std::hash;
181
182 using std::nullopt;
183 using std::nullopt_t;
184
185 using std::operator==;
186 using std::operator!=;
187 using std::operator<;
188 using std::operator<=;
189 using std::operator>;
190 using std::operator>=;
191 using std::make_optional;
192 using std::swap;
193}
194
195#else // optional_USES_STD_OPTIONAL
196
197#include <cassert>
198#include <utility>
199
200// optional-lite alignment configuration:
201
202#ifndef optional_CONFIG_MAX_ALIGN_HACK
203# define optional_CONFIG_MAX_ALIGN_HACK 0
204#endif
205
206#ifndef optional_CONFIG_ALIGN_AS
207// no default, used in #if defined()
208#endif
209
210#ifndef optional_CONFIG_ALIGN_AS_FALLBACK
211# define optional_CONFIG_ALIGN_AS_FALLBACK double
212#endif
213
214// Compiler warning suppression:
215
216#if defined(__clang__)
217# pragma clang diagnostic push
218# pragma clang diagnostic ignored "-Wundef"
219#elif defined(__GNUC__)
220# pragma GCC diagnostic push
221# pragma GCC diagnostic ignored "-Wundef"
222#elif defined(_MSC_VER )
223# pragma warning( push )
224#endif
225
226// half-open range [lo..hi):
227#define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
228
229// Compiler versions:
230//
231// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
232// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
233// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
234// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
235// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
236// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
237// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
238// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
239// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
240// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
241
242#if defined(_MSC_VER ) && !defined(__clang__)
243# define optional_COMPILER_MSVC_VER (_MSC_VER )
244# define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
245#else
246# define optional_COMPILER_MSVC_VER 0
247# define optional_COMPILER_MSVC_VERSION 0
248#endif
249
250#define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * (major) + (minor) ) + (patch) )
251
252#if defined(__GNUC__) && !defined(__clang__)
253# define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
254#else
255# define optional_COMPILER_GNUC_VERSION 0
256#endif
257
258#if defined(__clang__)
259# define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
260#else
261# define optional_COMPILER_CLANG_VERSION 0
262#endif
263
264#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
265# pragma warning( disable: 4345 ) // initialization behavior changed
266#endif
267
268#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
269# pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const'
270#endif
271
272// Presence of language and library features:
273
274#define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
275
276#ifdef _HAS_CPP0X
277# define optional_HAS_CPP0X _HAS_CPP0X
278#else
279# define optional_HAS_CPP0X 0
280#endif
281
282// Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
283
284#if optional_COMPILER_MSVC_VER >= 1900
285# undef optional_CPP11_OR_GREATER
286# define optional_CPP11_OR_GREATER 1
287#endif
288
289#define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
290#define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
291#define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
292#define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
293#define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
294#define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
295
296#define optional_CPP14_000 (optional_CPP14_OR_GREATER)
297#define optional_CPP17_000 (optional_CPP17_OR_GREATER)
298
299// Presence of C++11 language features:
300
301#define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
302#define optional_HAVE_IS_DEFAULT optional_CPP11_140
303#define optional_HAVE_NOEXCEPT optional_CPP11_140
304#define optional_HAVE_NULLPTR optional_CPP11_100
305#define optional_HAVE_REF_QUALIFIER optional_CPP11_140
306
307// Presence of C++14 language features:
308
309#define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
310
311// Presence of C++17 language features:
312
313#define optional_HAVE_NODISCARD optional_CPP17_000
314
315// Presence of C++ library features:
316
317#define optional_HAVE_CONDITIONAL optional_CPP11_120
318#define optional_HAVE_REMOVE_CV optional_CPP11_120
319#define optional_HAVE_TYPE_TRAITS optional_CPP11_90
320
321#define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
322#define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )
323
324// C++ feature usage:
325
326#if optional_HAVE( CONSTEXPR_11 )
327# define optional_constexpr constexpr
328#else
329# define optional_constexpr /*constexpr*/
330#endif
331
332#if optional_HAVE( IS_DEFAULT )
333# define optional_is_default = default;
334#else
335# define optional_is_default {}
336#endif
337
338#if optional_HAVE( CONSTEXPR_14 )
339# define optional_constexpr14 constexpr
340#else
341# define optional_constexpr14 /*constexpr*/
342#endif
343
344#if optional_HAVE( NODISCARD )
345# define optional_nodiscard [[nodiscard]]
346#else
347# define optional_nodiscard /*[[nodiscard]]*/
348#endif
349
350#if optional_HAVE( NOEXCEPT )
351# define optional_noexcept noexcept
352#else
353# define optional_noexcept /*noexcept*/
354#endif
355
356#if optional_HAVE( NULLPTR )
357# define optional_nullptr nullptr
358#else
359# define optional_nullptr NULL
360#endif
361
362#if optional_HAVE( REF_QUALIFIER )
363// NOLINTNEXTLINE( bugprone-macro-parentheses )
364# define optional_ref_qual &
365# define optional_refref_qual &&
366#else
367# define optional_ref_qual /*&*/
368# define optional_refref_qual /*&&*/
369#endif
370
371// additional includes:
372
373#if optional_CONFIG_NO_EXCEPTIONS
374// already included: <cassert>
375#else
376# include <stdexcept>
377#endif
378
379#if optional_CPP11_OR_GREATER
380# include <functional>
381#endif
382
383#if optional_HAVE( INITIALIZER_LIST )
384# include <initializer_list>
385#endif
386
387#if optional_HAVE( TYPE_TRAITS )
388# include <type_traits>
389#elif optional_HAVE( TR1_TYPE_TRAITS )
390# include <tr1/type_traits>
391#endif
392
393// Method enabling
394
395#if optional_CPP11_OR_GREATER
396
397#define optional_REQUIRES_0(...) \
398 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
399
400#define optional_REQUIRES_T(...) \
401 , typename = typename std::enable_if< (__VA_ARGS__), nonstd::optional_lite::detail::enabler >::type
402
403#define optional_REQUIRES_R(R, ...) \
404 typename std::enable_if< (__VA_ARGS__), R>::type
405
406#define optional_REQUIRES_A(...) \
407 , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
408
409#endif
410
411//
412// optional:
413//
414
415namespace nonstd { namespace optional_lite {
416
417namespace std11 {
418
419#if optional_CPP11_OR_GREATER
420 using std::move;
421#else
422 template< typename T > T & move( T & t ) { return t; }
423#endif
424
425#if optional_HAVE( CONDITIONAL )
426 using std::conditional;
427#else
428 template< bool B, typename T, typename F > struct conditional { typedef T type; };
429 template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
430#endif // optional_HAVE_CONDITIONAL
431
432} // namespace std11
433
434#if optional_CPP11_OR_GREATER
435
436/// type traits C++17:
437
438namespace std17 {
439
440#if optional_CPP17_OR_GREATER
441
442using std::is_swappable;
443using std::is_nothrow_swappable;
444
445#elif optional_CPP11_OR_GREATER
446
447namespace detail {
448
449using std::swap;
450
451struct is_swappable
452{
453 template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
454 static std::true_type test( int /*unused*/ );
455
456 template< typename >
457 static std::false_type test(...);
458};
459
460struct is_nothrow_swappable
461{
462 // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
463
464 template< typename T >
465 static constexpr bool satisfies()
466 {
467 return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
468 }
469
470 template< typename T >
471 static auto test( int /*unused*/ ) -> std::integral_constant<bool, satisfies<T>()>{}
472
473 template< typename >
474 static auto test(...) -> std::false_type;
475};
476
477} // namespace detail
478
479// is [nothow] swappable:
480
481template< typename T >
482struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
483
484template< typename T >
485struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
486
487#endif // optional_CPP17_OR_GREATER
488
489} // namespace std17
490
491/// type traits C++20:
492
493namespace std20 {
494
495template< typename T >
496struct remove_cvref
497{
498 typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
499};
500
501} // namespace std20
502
503#endif // optional_CPP11_OR_GREATER
504
505/// class optional
506
507template< typename T >
508class optional;
509
510namespace detail {
511
512// for optional_REQUIRES_T
513
514#if optional_CPP11_OR_GREATER
515enum class enabler{};
516#endif
517
518// C++11 emulation:
519
520struct nulltype{};
521
522template< typename Head, typename Tail >
523struct typelist
524{
525 typedef Head head;
526 typedef Tail tail;
527};
528
529#if optional_CONFIG_MAX_ALIGN_HACK
530
531// Max align, use most restricted type for alignment:
532
533#define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ )
534#define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
535#define optional_UNIQUE3( name, line ) name ## line
536
537#define optional_ALIGN_TYPE( type ) \
538 type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
539
540template< typename T >
541struct struct_t { T _; };
542
543union max_align_t
544{
545 optional_ALIGN_TYPE( char );
546 optional_ALIGN_TYPE( short int );
547 optional_ALIGN_TYPE( int );
548 optional_ALIGN_TYPE( long int );
549 optional_ALIGN_TYPE( float );
550 optional_ALIGN_TYPE( double );
551 optional_ALIGN_TYPE( long double );
552 optional_ALIGN_TYPE( char * );
553 optional_ALIGN_TYPE( short int * );
554 optional_ALIGN_TYPE( int * );
555 optional_ALIGN_TYPE( long int * );
556 optional_ALIGN_TYPE( float * );
557 optional_ALIGN_TYPE( double * );
558 optional_ALIGN_TYPE( long double * );
559 optional_ALIGN_TYPE( void * );
560
561#ifdef HAVE_LONG_LONG
562 optional_ALIGN_TYPE( long long );
563#endif
564
565 struct Unknown;
566
567 Unknown ( * optional_UNIQUE(_) )( Unknown );
568 Unknown * Unknown::* optional_UNIQUE(_);
569 Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
570
571 struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_);
572 struct_t< Unknown * Unknown::* > optional_UNIQUE(_);
573 struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
574};
575
576#undef optional_UNIQUE
577#undef optional_UNIQUE2
578#undef optional_UNIQUE3
579
580#undef optional_ALIGN_TYPE
581
582#elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
583
584// Use user-specified type for alignment:
585
586#define optional_ALIGN_AS( unused ) \
587 optional_CONFIG_ALIGN_AS
588
589#else // optional_CONFIG_MAX_ALIGN_HACK
590
591// Determine POD type to use for alignment:
592
593#define optional_ALIGN_AS( to_align ) \
594 typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
595
596template< typename T >
597struct alignment_of;
598
599template< typename T >
600struct alignment_of_hack
601{
602 char c;
603 T t;
604 alignment_of_hack();
605};
606
607template< size_t A, size_t S >
608struct alignment_logic
609{
610 enum { value = A < S ? A : S };
611};
612
613template< typename T >
614struct alignment_of
615{
616 enum { value = alignment_logic<
617 sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
618};
619
620template< typename List, size_t N >
621struct type_of_size
622{
623 typedef typename std11::conditional<
624 N == sizeof( typename List::head ),
625 typename List::head,
626 typename type_of_size<typename List::tail, N >::type >::type type;
627};
628
629template< size_t N >
630struct type_of_size< nulltype, N >
631{
632 typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
633};
634
635template< typename T>
636struct struct_t { T _; };
637
638#define optional_ALIGN_TYPE( type ) \
639 typelist< type , typelist< struct_t< type >
640
641struct Unknown;
642
643typedef
644 optional_ALIGN_TYPE( char ),
645 optional_ALIGN_TYPE( short ),
646 optional_ALIGN_TYPE( int ),
647 optional_ALIGN_TYPE( long), optional_ALIGN_TYPE(float), optional_ALIGN_TYPE(double),
648 optional_ALIGN_TYPE(long double),
649
650 optional_ALIGN_TYPE(char*), optional_ALIGN_TYPE(short*), optional_ALIGN_TYPE(int*),
651 optional_ALIGN_TYPE(long*), optional_ALIGN_TYPE(float*), optional_ALIGN_TYPE(double*),
652 optional_ALIGN_TYPE(long double*),
653
654 optional_ALIGN_TYPE(Unknown (*)(Unknown)), optional_ALIGN_TYPE(Unknown* Unknown::*),
655 optional_ALIGN_TYPE(Unknown (Unknown::*)(Unknown)),
656
657 nulltype >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> alignment_types;
658
659#undef optional_ALIGN_TYPE
660
661#endif // optional_CONFIG_MAX_ALIGN_HACK
662
663/// C++03 constructed union to hold value.
664
665template <typename T>
666union storage_t {
667 // private:
668 // template< typename > friend class optional;
669
670 typedef T value_type;
671
672 storage_t() optional_is_default
673
674 explicit storage_t(value_type const& v) {
675 construct_value(v);
676 }
677
678 void construct_value(value_type const& v) { ::new (value_ptr()) value_type(v); }
679
680#if optional_CPP11_OR_GREATER
681
682 explicit storage_t(value_type&& v) { construct_value(std::move(v)); }
683
684 void construct_value(value_type&& v) { ::new (value_ptr()) value_type(std::move(v)); }
685
686 template <class... Args>
687 void emplace(Args&&... args) {
688 ::new (value_ptr()) value_type(std::forward<Args>(args)...);
689 }
690
691 template <class U, class... Args>
692 void emplace(std::initializer_list<U> il, Args&&... args) {
693 ::new (value_ptr()) value_type(il, std::forward<Args>(args)...);
694 }
695
696#endif
697
698 void destruct_value() { value_ptr()->~T(); }
699
700 optional_nodiscard value_type const* value_ptr() const { return as<value_type>(); }
701
702 value_type* value_ptr() { return as<value_type>(); }
703
704 optional_nodiscard value_type const& value() const optional_ref_qual {
705 return *value_ptr();
706 }
707
708 value_type& value() optional_ref_qual { return *value_ptr(); }
709
710#if optional_CPP11_OR_GREATER
711
712 optional_nodiscard value_type const&& value() const optional_refref_qual {
713 return std::move(value());
714 }
715
716 value_type&& value() optional_refref_qual { return std::move(value()); }
717
718#endif
719
720#if optional_CPP11_OR_GREATER
721
722 using aligned_storage_t =
723 typename std::aligned_storage<sizeof(value_type), alignof(value_type)>::type;
724 aligned_storage_t data;
725
726#elif optional_CONFIG_MAX_ALIGN_HACK
727
728 typedef struct {
729 unsigned char data[sizeof(value_type)];
730 } aligned_storage_t;
731
732 max_align_t hack;
733 aligned_storage_t data;
734
735#else
736 typedef optional_ALIGN_AS(value_type) align_as_type;
737
738 typedef struct {
739 align_as_type data[1 + (sizeof(value_type) - 1) / sizeof(align_as_type)];
740 } aligned_storage_t;
741 aligned_storage_t data;
742
743#undef optional_ALIGN_AS
744
745#endif // optional_CONFIG_MAX_ALIGN_HACK
746
747 optional_nodiscard void* ptr() optional_noexcept { return &data; }
748
749 optional_nodiscard void const* ptr() const optional_noexcept { return &data; }
750
751 template <typename U>
752 optional_nodiscard U* as() {
753 return reinterpret_cast<U*>(ptr());
754 }
755
756 template <typename U>
757 optional_nodiscard U const* as() const {
758 return reinterpret_cast<U const*>(ptr());
759 }
760};
761
762} // namespace detail
763
764/// disengaged state tag
765
766struct nullopt_t {
767 struct init {};
768 explicit optional_constexpr nullopt_t(init /*unused*/) optional_noexcept {}
769};
770
771#if optional_HAVE(CONSTEXPR_11)
772constexpr nullopt_t nullopt{nullopt_t::init{}};
773#else
774// extra parenthesis to prevent the most vexing parse:
775const nullopt_t nullopt((nullopt_t::init()));
776#endif
777
778/// optional access error
779
780#if !optional_CONFIG_NO_EXCEPTIONS
781
782class bad_optional_access : public std::logic_error {
783 public:
784 explicit bad_optional_access() : logic_error("bad optional access") {}
785};
786
787#endif // optional_CONFIG_NO_EXCEPTIONS
788
789/// optional
790
791template <typename T>
792class optional {
793 private:
794 template <typename>
795 friend class optional;
796
797 typedef void (optional::*safe_bool)() const;
798
799 public:
800 typedef T value_type;
801
802 // x.x.3.1, constructors
803
804 // 1a - default construct
805 optional_constexpr optional() optional_noexcept : has_value_(false), contained() {}
806
807 // 1b - construct explicitly empty
808 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
809 optional_constexpr optional(nullopt_t /*unused*/) optional_noexcept : has_value_(false),
810 contained() {}
811
812 // 2 - copy-construct
813 optional_constexpr14 optional(
814 optional const& other
815#if optional_CPP11_OR_GREATER
816 optional_REQUIRES_A(true || std::is_copy_constructible<T>::value)
817#endif
818 )
819 : has_value_(other.has_value()) {
820 if (other.has_value()) {
821 contained.construct_value(other.contained.value());
822 }
823 }
824
825#if optional_CPP11_OR_GREATER
826
827 // 3 (C++11) - move-construct from optional
828 optional_constexpr14 optional(
829 optional&& other optional_REQUIRES_A(true || std::is_move_constructible<T>::value)
830 // NOLINTNEXTLINE( performance-noexcept-move-constructor )
831 ) noexcept(std::is_nothrow_move_constructible<T>::value)
832 : has_value_(other.has_value()) {
833 if (other.has_value()) {
834 contained.construct_value(std::move(other.contained.value()));
835 }
836 }
837
838 // 4a (C++11) - explicit converting copy-construct from optional
839 template <typename U>
840 explicit optional(optional<U> const& other optional_REQUIRES_A(
841 std::is_constructible<T, U const&>::value &&
842 !std::is_constructible<T, optional<U>&>::value &&
843 !std::is_constructible<T, optional<U>&&>::value &&
844 !std::is_constructible<T, optional<U> const&>::value &&
845 !std::is_constructible<T, optional<U> const&&>::value &&
846 !std::is_convertible<optional<U>&, T>::value &&
847 !std::is_convertible<optional<U>&&, T>::value &&
848 !std::is_convertible<optional<U> const&, T>::value &&
849 !std::is_convertible<optional<U> const&&, T>::value &&
850 !std::is_convertible<U const&, T>::value /*=> explicit */
851 ))
852 : has_value_(other.has_value()) {
853 if (other.has_value()) {
854 contained.construct_value(T{other.contained.value()});
855 }
856 }
857#endif // optional_CPP11_OR_GREATER
858
859 // 4b (C++98 and later) - non-explicit converting copy-construct from optional
860 template <typename U>
861 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
862 optional(
863 optional<U> const& other
864#if optional_CPP11_OR_GREATER
865 optional_REQUIRES_A(std::is_constructible<T, U const&>::value &&
866 !std::is_constructible<T, optional<U>&>::value &&
867 !std::is_constructible<T, optional<U>&&>::value &&
868 !std::is_constructible<T, optional<U> const&>::value &&
869 !std::is_constructible<T, optional<U> const&&>::value &&
870 !std::is_convertible<optional<U>&, T>::value &&
871 !std::is_convertible<optional<U>&&, T>::value &&
872 !std::is_convertible<optional<U> const&, T>::value &&
873 !std::is_convertible<optional<U> const&&, T>::value &&
874 std::is_convertible<U const&, T>::value /*=> non-explicit */
875 )
876#endif // optional_CPP11_OR_GREATER
877 )
878 : has_value_(other.has_value()) {
879 if (other.has_value()) {
880 contained.construct_value(other.contained.value());
881 }
882 }
883
884#if optional_CPP11_OR_GREATER
885
886 // 5a (C++11) - explicit converting move-construct from optional
887 template <typename U>
888 explicit optional(optional<U>&& other optional_REQUIRES_A(
889 std::is_constructible<T, U&&>::value &&
890 !std::is_constructible<T, optional<U>&>::value &&
891 !std::is_constructible<T, optional<U>&&>::value &&
892 !std::is_constructible<T, optional<U> const&>::value &&
893 !std::is_constructible<T, optional<U> const&&>::value &&
894 !std::is_convertible<optional<U>&, T>::value &&
895 !std::is_convertible<optional<U>&&, T>::value &&
896 !std::is_convertible<optional<U> const&, T>::value &&
897 !std::is_convertible<optional<U> const&&, T>::value &&
898 !std::is_convertible<U&&, T>::value /*=> explicit */
899 ))
900 : has_value_(other.has_value()) {
901 if (other.has_value()) {
902 contained.construct_value(T{std::move(other.contained.value())});
903 }
904 }
905
906 // 5a (C++11) - non-explicit converting move-construct from optional
907 template <typename U>
908 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
909 optional(optional<U>&& other optional_REQUIRES_A(
910 std::is_constructible<T, U&&>::value &&
911 !std::is_constructible<T, optional<U>&>::value &&
912 !std::is_constructible<T, optional<U>&&>::value &&
913 !std::is_constructible<T, optional<U> const&>::value &&
914 !std::is_constructible<T, optional<U> const&&>::value &&
915 !std::is_convertible<optional<U>&, T>::value &&
916 !std::is_convertible<optional<U>&&, T>::value &&
917 !std::is_convertible<optional<U> const&, T>::value &&
918 !std::is_convertible<optional<U> const&&, T>::value &&
919 std::is_convertible<U&&, T>::value /*=> non-explicit */
920 ))
921 : has_value_(other.has_value()) {
922 if (other.has_value()) {
923 contained.construct_value(std::move(other.contained.value()));
924 }
925 }
926
927 // 6 (C++11) - in-place construct
928 template <
929 typename... Args optional_REQUIRES_T(std::is_constructible<T, Args&&...>::value)>
930 optional_constexpr explicit optional(nonstd_lite_in_place_t(T), Args&&... args)
931 : has_value_(true), contained(T(std::forward<Args>(args)...)) {}
932
933 // 7 (C++11) - in-place construct, initializer-list
934 template <typename U,
935 typename... Args optional_REQUIRES_T(
936 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value)>
937 optional_constexpr explicit optional(nonstd_lite_in_place_t(T),
938 std::initializer_list<U> il, Args&&... args)
939 : has_value_(true), contained(T(il, std::forward<Args>(args)...)) {}
940
941 // 8a (C++11) - explicit move construct from value
942 template <typename U = value_type>
943 optional_constexpr explicit optional(U&& value optional_REQUIRES_A(
944 std::is_constructible<T, U&&>::value &&
945 !std::is_same<typename std20::remove_cvref<U>::type,
946 nonstd_lite_in_place_t(U)>::value &&
947 !std::is_same<typename std20::remove_cvref<U>::type, optional<T> >::value &&
948 !std::is_convertible<U&&, T>::value /*=> explicit */
949 ))
950 : has_value_(true), contained(T{std::forward<U>(value)}) {}
951
952 // 8b (C++11) - non-explicit move construct from value
953 template <typename U = value_type>
954 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
955 optional_constexpr optional(U&& value optional_REQUIRES_A(
956 std::is_constructible<T, U&&>::value &&
957 !std::is_same<typename std20::remove_cvref<U>::type,
958 nonstd_lite_in_place_t(U)>::value &&
959 !std::is_same<typename std20::remove_cvref<U>::type, optional<T> >::value &&
960 std::is_convertible<U&&, T>::value /*=> non-explicit */
961 ))
962 : has_value_(true), contained(std::forward<U>(value)) {}
963
964#else // optional_CPP11_OR_GREATER
965
966 // 8 (C++98)
967 optional(value_type const& value) : has_value_(true), contained(value) {}
968
969#endif // optional_CPP11_OR_GREATER
970
971 // x.x.3.2, destructor
972
973 ~optional() {
974 if (has_value()) {
975 contained.destruct_value();
976 }
977 }
978
979 // x.x.3.3, assignment
980
981 // 1 (C++98and later) - assign explicitly empty
982 optional& operator=(nullopt_t /*unused*/) optional_noexcept {
983 reset();
984 return *this;
985 }
986
987 // 2 (C++98and later) - copy-assign from optional
988#if optional_CPP11_OR_GREATER
989 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
990 // misc-unconventional-assign-operator )
991 optional_REQUIRES_R(optional&, true
992 // std::is_copy_constructible<T>::value
993 // && std::is_copy_assignable<T>::value
994 )
995 operator=(optional const& other) noexcept(
996 std::is_nothrow_move_assignable<T>::value&&
997 std::is_nothrow_move_constructible<T>::value)
998#else
999 optional& operator=(optional const& other)
1000#endif
1001 {
1002 if ((has_value() == true) && (other.has_value() == false)) {
1003 reset();
1004 } else if ((has_value() == false) && (other.has_value() == true)) {
1005 initialize(*other);
1006 } else if ((has_value() == true) && (other.has_value() == true)) {
1007 contained.value() = *other;
1008 }
1009 return *this;
1010 }
1011
1012#if optional_CPP11_OR_GREATER
1013
1014 // 3 (C++11) - move-assign from optional
1015 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
1016 // misc-unconventional-assign-operator )
1017 optional_REQUIRES_R(optional&, true
1018 // std::is_move_constructible<T>::value
1019 // && std::is_move_assignable<T>::value
1020 )
1021 operator=(optional&& other) noexcept {
1022 if ((has_value() == true) && (other.has_value() == false)) {
1023 reset();
1024 } else if ((has_value() == false) && (other.has_value() == true)) {
1025 initialize(std::move(*other));
1026 } else if ((has_value() == true) && (other.has_value() == true)) {
1027 contained.value() = std::move(*other);
1028 }
1029 return *this;
1030 }
1031
1032 // 4 (C++11) - move-assign from value
1033 template <typename U = T>
1034 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
1035 // misc-unconventional-assign-operator )
1036 optional_REQUIRES_R(
1037 optional&,
1038 std::is_constructible<T, U>::value&& std::is_assignable<T&, U>::value &&
1039 !std::is_same<typename std20::remove_cvref<U>::type,
1040 nonstd_lite_in_place_t(U)>::value &&
1041 !std::is_same<typename std20::remove_cvref<U>::type, optional<T> >::value &&
1042 !(std::is_scalar<T>::value &&
1043 std::is_same<T, typename std::decay<U>::type>::value))
1044 operator=(U&& value) {
1045 if (has_value()) {
1046 contained.value() = std::forward<U>(value);
1047 } else {
1048 initialize(T(std::forward<U>(value)));
1049 }
1050 return *this;
1051 }
1052
1053#else // optional_CPP11_OR_GREATER
1054
1055 // 4 (C++98) - copy-assign from value
1056 template <typename U /*= T*/>
1057 optional& operator=(U const& value) {
1058 if (has_value())
1059 contained.value() = value;
1060 else
1061 initialize(T(value));
1062 return *this;
1063 }
1064
1065#endif // optional_CPP11_OR_GREATER
1066
1067 // 5 (C++98 and later) - converting copy-assign from optional
1068 template <typename U>
1069#if optional_CPP11_OR_GREATER
1070 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
1071 // misc-unconventional-assign-operator )
1072 optional_REQUIRES_R(optional&,
1073 std::is_constructible<T, U const&>::value&&
1074 std::is_assignable<T&, U const&>::value &&
1075 !std::is_constructible<T, optional<U>&>::value &&
1076 !std::is_constructible<T, optional<U>&&>::value &&
1077 !std::is_constructible<T, optional<U> const&>::value &&
1078 !std::is_constructible<T, optional<U> const&&>::value &&
1079 !std::is_convertible<optional<U>&, T>::value &&
1080 !std::is_convertible<optional<U>&&, T>::value &&
1081 !std::is_convertible<optional<U> const&, T>::value &&
1082 !std::is_convertible<optional<U> const&&, T>::value &&
1083 !std::is_assignable<T&, optional<U>&>::value &&
1084 !std::is_assignable<T&, optional<U>&&>::value &&
1085 !std::is_assignable<T&, optional<U> const&>::value &&
1086 !std::is_assignable<T&, optional<U> const&&>::value)
1087#else
1088 optional&
1089#endif // optional_CPP11_OR_GREATER
1090 operator=(optional<U> const& other) {
1091 return *this = optional(other);
1092 }
1093
1094#if optional_CPP11_OR_GREATER
1095
1096 // 6 (C++11) - converting move-assign from optional
1097 template <typename U>
1098 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
1099 // misc-unconventional-assign-operator )
1100 optional_REQUIRES_R(
1101 optional&, std::is_constructible<T, U>::value&& std::is_assignable<T&, U>::value &&
1102 !std::is_constructible<T, optional<U>&>::value &&
1103 !std::is_constructible<T, optional<U>&&>::value &&
1104 !std::is_constructible<T, optional<U> const&>::value &&
1105 !std::is_constructible<T, optional<U> const&&>::value &&
1106 !std::is_convertible<optional<U>&, T>::value &&
1107 !std::is_convertible<optional<U>&&, T>::value &&
1108 !std::is_convertible<optional<U> const&, T>::value &&
1109 !std::is_convertible<optional<U> const&&, T>::value &&
1110 !std::is_assignable<T&, optional<U>&>::value &&
1111 !std::is_assignable<T&, optional<U>&&>::value &&
1112 !std::is_assignable<T&, optional<U> const&>::value &&
1113 !std::is_assignable<T&, optional<U> const&&>::value)
1114 operator=(optional<U>&& other) {
1115 return *this = optional(std::move(other));
1116 }
1117
1118 // 7 (C++11) - emplace
1119 template <
1120 typename... Args optional_REQUIRES_T(std::is_constructible<T, Args&&...>::value)>
1121 T& emplace(Args&&... args) {
1122 *this = nullopt;
1123 contained.emplace(std::forward<Args>(args)...);
1124 has_value_ = true;
1125 return contained.value();
1126 }
1127
1128 // 8 (C++11) - emplace, initializer-list
1129 template <typename U,
1130 typename... Args optional_REQUIRES_T(
1131 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value)>
1132 T& emplace(std::initializer_list<U> il, Args&&... args) {
1133 *this = nullopt;
1134 contained.emplace(il, std::forward<Args>(args)...);
1135 has_value_ = true;
1136 return contained.value();
1137 }
1138
1139#endif // optional_CPP11_OR_GREATER
1140
1141 // x.x.3.4, swap
1142
1143 void swap(optional& other)
1144#if optional_CPP11_OR_GREATER
1145 noexcept(std::is_nothrow_move_constructible<T>::value&&
1146 std17::is_nothrow_swappable<T>::value)
1147#endif
1148 {
1149 using std::swap;
1150 if ((has_value() == true) && (other.has_value() == true)) {
1151 swap(**this, *other);
1152 } else if ((has_value() == false) && (other.has_value() == true)) {
1153 initialize(std11::move(*other));
1154 other.reset();
1155 } else if ((has_value() == true) && (other.has_value() == false)) {
1156 other.initialize(std11::move(**this));
1157 reset();
1158 }
1159 }
1160
1161 // x.x.3.5, observers
1162
1163 optional_constexpr value_type const* operator->() const {
1164 return assert(has_value()), contained.value_ptr();
1165 }
1166
1167 optional_constexpr14 value_type* operator->() {
1168 return assert(has_value()), contained.value_ptr();
1169 }
1170
1171 optional_constexpr value_type const& operator*() const optional_ref_qual {
1172 return assert(has_value()), contained.value();
1173 }
1174
1175 optional_constexpr14 value_type& operator*() optional_ref_qual {
1176 return assert(has_value()), contained.value();
1177 }
1178
1179#if optional_HAVE(REF_QUALIFIER) && \
1180 (!optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490)
1181
1182 optional_constexpr value_type const&& operator*() const optional_refref_qual {
1183 return std::move(**this);
1184 }
1185
1186 optional_constexpr14 value_type&& operator*() optional_refref_qual {
1187 return std::move(**this);
1188 }
1189
1190#endif
1191
1192#if optional_CPP11_OR_GREATER
1193 optional_constexpr explicit operator bool() const optional_noexcept {
1194 return has_value();
1195 }
1196#else
1197 optional_constexpr operator safe_bool() const optional_noexcept {
1198 return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
1199 }
1200#endif
1201
1202 // NOLINTNEXTLINE( modernize-use-nodiscard )
1203 /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept {
1204 return has_value_;
1205 }
1206
1207 // NOLINTNEXTLINE( modernize-use-nodiscard )
1208 /*optional_nodiscard*/ optional_constexpr14 value_type const& value() const
1209 optional_ref_qual {
1210#if optional_CONFIG_NO_EXCEPTIONS
1211 assert(has_value());
1212#else
1213 if (!has_value()) {
1214 throw bad_optional_access();
1215 }
1216#endif
1217 return contained.value();
1218 }
1219
1220 optional_constexpr14 value_type& value() optional_ref_qual {
1221#if optional_CONFIG_NO_EXCEPTIONS
1222 assert(has_value());
1223#else
1224 if (!has_value()) {
1225 throw bad_optional_access();
1226 }
1227#endif
1228 return contained.value();
1229 }
1230
1231#if optional_HAVE(REF_QUALIFIER) && \
1232 (!optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490)
1233
1234 // NOLINTNEXTLINE( modernize-use-nodiscard )
1235 /*optional_nodiscard*/ optional_constexpr value_type const&& value() const
1236 optional_refref_qual {
1237 return std::move(value());
1238 }
1239
1240 optional_constexpr14 value_type&& value() optional_refref_qual {
1241 return std::move(value());
1242 }
1243
1244#endif
1245
1246#if optional_CPP11_OR_GREATER
1247
1248 template <typename U>
1249 optional_constexpr value_type value_or(U&& v) const optional_ref_qual {
1250 return has_value() ? contained.value() : static_cast<T>(std::forward<U>(v));
1251 }
1252
1253 template <typename U>
1254 optional_constexpr14 value_type value_or(U&& v) optional_refref_qual {
1255 return has_value() ? std::move(contained.value())
1256 : static_cast<T>(std::forward<U>(v));
1257 }
1258
1259#else
1260
1261 template <typename U>
1262 optional_constexpr value_type value_or(U const& v) const {
1263 return has_value() ? contained.value() : static_cast<value_type>(v);
1264 }
1265
1266#endif // optional_CPP11_OR_GREATER
1267
1268 // x.x.3.6, modifiers
1269
1270 void reset() optional_noexcept {
1271 if (has_value()) {
1272 contained.destruct_value();
1273 }
1274
1275 has_value_ = false;
1276 }
1277
1278 private:
1279 void this_type_does_not_support_comparisons() const {}
1280
1281 template <typename V>
1282 void initialize(V const& value) {
1283 assert(!has_value());
1284 contained.construct_value(value);
1285 has_value_ = true;
1286 }
1287
1288#if optional_CPP11_OR_GREATER
1289 template <typename V>
1290 void initialize(V&& value) {
1291 assert(!has_value());
1292 contained.construct_value(std::move(value));
1293 has_value_ = true;
1294 }
1295
1296#endif
1297
1298 private:
1299 bool has_value_;
1300 detail::storage_t<value_type> contained;
1301};
1302
1303// Relational operators
1304
1305template <typename T, typename U>
1306inline optional_constexpr bool operator==(optional<T> const& x, optional<U> const& y) {
1307 return bool(x) != bool(y) ? false : !bool(x) ? true : *x == *y;
1308}
1309
1310template <typename T, typename U>
1311inline optional_constexpr bool operator!=(optional<T> const& x, optional<U> const& y) {
1312 return !(x == y);
1313}
1314
1315template <typename T, typename U>
1316inline optional_constexpr bool operator<(optional<T> const& x, optional<U> const& y) {
1317 return (!y) ? false : (!x) ? true : *x < *y;
1318}
1319
1320template <typename T, typename U>
1321inline optional_constexpr bool operator>(optional<T> const& x, optional<U> const& y) {
1322 return (y < x);
1323}
1324
1325template <typename T, typename U>
1326inline optional_constexpr bool operator<=(optional<T> const& x, optional<U> const& y) {
1327 return !(y < x);
1328}
1329
1330template <typename T, typename U>
1331inline optional_constexpr bool operator>=(optional<T> const& x, optional<U> const& y) {
1332 return !(x < y);
1333}
1334
1335// Comparison with nullopt
1336
1337template <typename T>
1338inline optional_constexpr bool operator==(optional<T> const& x,
1339 nullopt_t /*unused*/) optional_noexcept {
1340 return (!x);
1341}
1342
1343template <typename T>
1344inline optional_constexpr bool operator==(nullopt_t /*unused*/,
1345 optional<T> const& x) optional_noexcept {
1346 return (!x);
1347}
1348
1349template <typename T>
1350inline optional_constexpr bool operator!=(optional<T> const& x,
1351 nullopt_t /*unused*/) optional_noexcept {
1352 return bool(x);
1353}
1354
1355template <typename T>
1356inline optional_constexpr bool operator!=(nullopt_t /*unused*/,
1357 optional<T> const& x) optional_noexcept {
1358 return bool(x);
1359}
1360
1361template <typename T>
1362inline optional_constexpr bool operator<(optional<T> const& /*unused*/,
1363 nullopt_t /*unused*/) optional_noexcept {
1364 return false;
1365}
1366
1367template <typename T>
1368inline optional_constexpr bool operator<(nullopt_t /*unused*/,
1369 optional<T> const& x) optional_noexcept {
1370 return bool(x);
1371}
1372
1373template <typename T>
1374inline optional_constexpr bool operator<=(optional<T> const& x,
1375 nullopt_t /*unused*/) optional_noexcept {
1376 return (!x);
1377}
1378
1379template <typename T>
1380inline optional_constexpr bool operator<=(
1381 nullopt_t /*unused*/, optional<T> const& /*unused*/) optional_noexcept {
1382 return true;
1383}
1384
1385template <typename T>
1386inline optional_constexpr bool operator>(optional<T> const& x,
1387 nullopt_t /*unused*/) optional_noexcept {
1388 return bool(x);
1389}
1390
1391template <typename T>
1392inline optional_constexpr bool operator>(
1393 nullopt_t /*unused*/, optional<T> const& /*unused*/) optional_noexcept {
1394 return false;
1395}
1396
1397template <typename T>
1398inline optional_constexpr bool operator>=(optional<T> const& /*unused*/,
1399 nullopt_t /*unused*/) optional_noexcept {
1400 return true;
1401}
1402
1403template <typename T>
1404inline optional_constexpr bool operator>=(nullopt_t /*unused*/,
1405 optional<T> const& x) optional_noexcept {
1406 return (!x);
1407}
1408
1409// Comparison with T
1410
1411template <typename T, typename U>
1412inline optional_constexpr bool operator==(optional<T> const& x, U const& v) {
1413 return bool(x) ? *x == v : false;
1414}
1415
1416template <typename T, typename U>
1417inline optional_constexpr bool operator==(U const& v, optional<T> const& x) {
1418 return bool(x) ? v == *x : false;
1419}
1420
1421template <typename T, typename U>
1422inline optional_constexpr bool operator!=(optional<T> const& x, U const& v) {
1423 return bool(x) ? *x != v : true;
1424}
1425
1426template <typename T, typename U>
1427inline optional_constexpr bool operator!=(U const& v, optional<T> const& x) {
1428 return bool(x) ? v != *x : true;
1429}
1430
1431template <typename T, typename U>
1432inline optional_constexpr bool operator<(optional<T> const& x, U const& v) {
1433 return bool(x) ? *x < v : true;
1434}
1435
1436template <typename T, typename U>
1437inline optional_constexpr bool operator<(U const& v, optional<T> const& x) {
1438 return bool(x) ? v < *x : false;
1439}
1440
1441template <typename T, typename U>
1442inline optional_constexpr bool operator<=(optional<T> const& x, U const& v) {
1443 return bool(x) ? *x <= v : true;
1444}
1445
1446template <typename T, typename U>
1447inline optional_constexpr bool operator<=(U const& v, optional<T> const& x) {
1448 return bool(x) ? v <= *x : false;
1449}
1450
1451template <typename T, typename U>
1452inline optional_constexpr bool operator>(optional<T> const& x, U const& v) {
1453 return bool(x) ? *x > v : false;
1454}
1455
1456template <typename T, typename U>
1457inline optional_constexpr bool operator>(U const& v, optional<T> const& x) {
1458 return bool(x) ? v > *x : true;
1459}
1460
1461template <typename T, typename U>
1462inline optional_constexpr bool operator>=(optional<T> const& x, U const& v) {
1463 return bool(x) ? *x >= v : false;
1464}
1465
1466template <typename T, typename U>
1467inline optional_constexpr bool operator>=(U const& v, optional<T> const& x) {
1468 return bool(x) ? v >= *x : true;
1469}
1470
1471// Specialized algorithms
1472
1473template <typename T
1474#if optional_CPP11_OR_GREATER
1475 optional_REQUIRES_T(
1476 std::is_move_constructible<T>::value&& std17::is_swappable<T>::value)
1477#endif
1478 >
1479void swap(optional<T>& x, optional<T>& y)
1480#if optional_CPP11_OR_GREATER
1481 noexcept(noexcept(x.swap(y)))
1482#endif
1483{
1484 x.swap(y);
1485}
1486
1487#if optional_CPP11_OR_GREATER
1488
1489template <typename T>
1490optional_constexpr optional<typename std::decay<T>::type> make_optional(T&& value) {
1491 return optional<typename std::decay<T>::type>(std::forward<T>(value));
1492}
1493
1494template <typename T, typename... Args>
1495optional_constexpr optional<T> make_optional(Args&&... args) {
1496 return optional<T>(nonstd_lite_in_place(T), std::forward<Args>(args)...);
1497}
1498
1499template <typename T, typename U, typename... Args>
1500optional_constexpr optional<T> make_optional(std::initializer_list<U> il,
1501 Args&&... args) {
1502 return optional<T>(nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
1503}
1504
1505#else
1506
1507template <typename T>
1508optional<T> make_optional(T const& value) {
1509 return optional<T>(value);
1510}
1511
1512#endif // optional_CPP11_OR_GREATER
1513
1514} // namespace optional_lite
1515
1516using optional_lite::bad_optional_access;
1517using optional_lite::nullopt;
1518using optional_lite::nullopt_t;
1519using optional_lite::optional;
1520
1521using optional_lite::make_optional;
1522
1523} // namespace nonstd
1524
1525#if optional_CPP11_OR_GREATER
1526
1527// specialize the std::hash algorithm:
1528
1529namespace std {
1530
1531template <class T>
1532struct hash<nonstd::optional<T> > {
1533 public:
1534 std::size_t operator()(nonstd::optional<T> const& v) const optional_noexcept {
1535 return bool(v) ? std::hash<T>{}(*v) : 0;
1536 }
1537};
1538
1539} // namespace std
1540
1541#endif // optional_CPP11_OR_GREATER
1542
1543#if defined(__clang__)
1544#pragma clang diagnostic pop
1545#elif defined(__GNUC__)
1546#pragma GCC diagnostic pop
1547#elif defined(_MSC_VER)
1548#pragma warning(pop)
1549#endif
1550
1551#endif // optional_USES_STD_OPTIONAL
1552
1553#endif // NONSTD_OPTIONAL_LITE_HPP