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