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 >
120 
121 template< std::size_t K >
123 
124 } // namespace detail
125 
126 struct in_place_t {};
127 
128 template< class 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 optional_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
231 // MSVC++ 7.0 _MSC_VER == 1300 optional_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
232 // MSVC++ 7.1 _MSC_VER == 1310 optional_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
233 // MSVC++ 8.0 _MSC_VER == 1400 optional_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
234 // MSVC++ 9.0 _MSC_VER == 1500 optional_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
235 // MSVC++ 10.0 _MSC_VER == 1600 optional_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
236 // MSVC++ 11.0 _MSC_VER == 1700 optional_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
237 // MSVC++ 12.0 _MSC_VER == 1800 optional_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
238 // MSVC++ 14.0 _MSC_VER == 1900 optional_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
239 // MSVC++ 14.1 _MSC_VER >= 1910 optional_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
240 // MSVC++ 14.2 _MSC_VER >= 1920 optional_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
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_CPP11_140_490 ((optional_CPP11_OR_GREATER_ && optional_COMPILER_GNUC_VERSION >= 490) || (optional_COMPILER_MSVC_VER >= 1910))
297 
298 #define optional_CPP14_000 (optional_CPP14_OR_GREATER)
299 #define optional_CPP17_000 (optional_CPP17_OR_GREATER)
300 
301 // Presence of C++11 language features:
302 
303 #define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
304 #define optional_HAVE_IS_DEFAULT optional_CPP11_140
305 #define optional_HAVE_NOEXCEPT optional_CPP11_140
306 #define optional_HAVE_NULLPTR optional_CPP11_100
307 #define optional_HAVE_REF_QUALIFIER optional_CPP11_140_490
308 #define optional_HAVE_INITIALIZER_LIST optional_CPP11_140
309 
310 // Presence of C++14 language features:
311 
312 #define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
313 
314 // Presence of C++17 language features:
315 
316 #define optional_HAVE_NODISCARD optional_CPP17_000
317 
318 // Presence of C++ library features:
319 
320 #define optional_HAVE_CONDITIONAL optional_CPP11_120
321 #define optional_HAVE_REMOVE_CV optional_CPP11_120
322 #define optional_HAVE_TYPE_TRAITS optional_CPP11_90
323 
324 #define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
325 #define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )
326 
327 // C++ feature usage:
328 
329 #if optional_HAVE( CONSTEXPR_11 )
330 # define optional_constexpr constexpr
331 #else
332 # define optional_constexpr /*constexpr*/
333 #endif
334 
335 #if optional_HAVE( IS_DEFAULT )
336 # define optional_is_default = default;
337 #else
338 # define optional_is_default {}
339 #endif
340 
341 #if optional_HAVE( CONSTEXPR_14 )
342 # define optional_constexpr14 constexpr
343 #else
344 # define optional_constexpr14 /*constexpr*/
345 #endif
346 
347 #if optional_HAVE( NODISCARD )
348 # define optional_nodiscard [[nodiscard]]
349 #else
350 # define optional_nodiscard /*[[nodiscard]]*/
351 #endif
352 
353 #if optional_HAVE( NOEXCEPT )
354 # define optional_noexcept noexcept
355 #else
356 # define optional_noexcept /*noexcept*/
357 #endif
358 
359 #if optional_HAVE( NULLPTR )
360 # define optional_nullptr nullptr
361 #else
362 # define optional_nullptr NULL
363 #endif
364 
365 #if optional_HAVE( REF_QUALIFIER )
366 // NOLINTNEXTLINE( bugprone-macro-parentheses )
367 # define optional_ref_qual &
368 # define optional_refref_qual &&
369 #else
370 # define optional_ref_qual /*&*/
371 # define optional_refref_qual /*&&*/
372 #endif
373 
374 // additional includes:
375 
376 #if optional_CONFIG_NO_EXCEPTIONS
377 // already included: <cassert>
378 #else
379 # include <stdexcept>
380 #endif
381 
382 #if optional_CPP11_OR_GREATER
383 # include <functional>
384 #endif
385 
386 #if optional_HAVE( INITIALIZER_LIST )
387 # include <initializer_list>
388 #endif
389 
390 #if optional_HAVE( TYPE_TRAITS )
391 # include <type_traits>
392 #elif optional_HAVE( TR1_TYPE_TRAITS )
393 # include <tr1/type_traits>
394 #endif
395 
396 // Method enabling
397 
398 #if optional_CPP11_OR_GREATER
399 
400 #define optional_REQUIRES_0(...) \
401  template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
402 
403 #define optional_REQUIRES_T(...) \
404  , typename std::enable_if< (__VA_ARGS__), int >::type = 0
405 
406 #define optional_REQUIRES_R(R, ...) \
407  typename std::enable_if< (__VA_ARGS__), R>::type
408 
409 #define optional_REQUIRES_A(...) \
410  , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
411 
412 #endif
413 
414 //
415 // optional:
416 //
417 
418 namespace nonstd { namespace optional_lite {
419 
420 namespace std11 {
421 
422 #if optional_CPP11_OR_GREATER
423  using std::move;
424 #else
425  template< typename T > T & move( T & t ) { return t; }
426 #endif
427 
428 #if optional_HAVE( CONDITIONAL )
429  using std::conditional;
430 #else
431  template< bool B, typename T, typename F > struct conditional { typedef T type; };
432  template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
433 #endif // optional_HAVE_CONDITIONAL
434 
435 // gcc < 5:
436 #if optional_CPP11_OR_GREATER
437 #if optional_BETWEEN( optional_COMPILER_GNUC_VERSION, 1, 500 )
438  template< typename T > struct is_trivially_copy_constructible : std::true_type{};
439  template< typename T > struct is_trivially_move_constructible : std::true_type{};
440 #else
441  using std::is_trivially_copy_constructible;
442  using std::is_trivially_move_constructible;
443 #endif
444 #endif
445 } // namespace std11
446 
447 #if optional_CPP11_OR_GREATER
448 
450 
451 namespace std17 {
452 
453 #if optional_CPP17_OR_GREATER
454 
455 using std::is_swappable;
456 using std::is_nothrow_swappable;
457 
458 #elif optional_CPP11_OR_GREATER
459 
460 namespace detail {
461 
462 using std::swap;
463 
464 struct is_swappable
465 {
466  template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
467  static std::true_type test( int /*unused*/ );
468 
469  template< typename >
470  static std::false_type test(...);
471 };
472 
473 struct is_nothrow_swappable
474 {
475  // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
476 
477  template< typename T >
478  static constexpr bool satisfies()
479  {
480  return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
481  }
482 
483  template< typename T >
484  static auto test( int /*unused*/ ) -> std::integral_constant<bool, satisfies<T>()>{}
485 
486  template< typename >
487  static auto test(...) -> std::false_type;
488 };
489 
490 } // namespace detail
491 
492 // is [nothow] swappable:
493 
494 template< typename T >
495 struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
496 
497 template< typename T >
498 struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
499 
500 #endif // optional_CPP17_OR_GREATER
501 
502 } // namespace std17
503 
505 
506 namespace std20 {
507 
508 template< typename T >
509 struct remove_cvref
510 {
511  typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
512 };
513 
514 } // namespace std20
515 
516 #endif // optional_CPP11_OR_GREATER
517 
519 
520 template< typename T >
521 class optional;
522 
523 namespace detail {
524 
525 // C++11 emulation:
526 
527 struct nulltype{};
528 
529 template< typename Head, typename Tail >
530 struct typelist
531 {
532  typedef Head head;
533  typedef Tail tail;
534 };
535 
536 #if optional_CONFIG_MAX_ALIGN_HACK
537 
538 // Max align, use most restricted type for alignment:
539 
540 #define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ )
541 #define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
542 #define optional_UNIQUE3( name, line ) name ## line
543 
544 #define optional_ALIGN_TYPE( type ) \
545  type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
546 
547 template< typename T >
548 struct struct_t { T _; };
549 
550 union max_align_t
551 {
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( char * );
560  optional_ALIGN_TYPE( short int * );
561  optional_ALIGN_TYPE( int * );
562  optional_ALIGN_TYPE( long int * );
563  optional_ALIGN_TYPE( float * );
564  optional_ALIGN_TYPE( double * );
565  optional_ALIGN_TYPE( long double * );
566  optional_ALIGN_TYPE( void * );
567 
568 #ifdef HAVE_LONG_LONG
569  optional_ALIGN_TYPE( long long );
570 #endif
571 
572  struct Unknown;
573 
574  Unknown ( * optional_UNIQUE(_) )( Unknown );
575  Unknown * Unknown::* optional_UNIQUE(_);
576  Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
577 
578  struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_);
579  struct_t< Unknown * Unknown::* > optional_UNIQUE(_);
580  struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
581 };
582 
583 #undef optional_UNIQUE
584 #undef optional_UNIQUE2
585 #undef optional_UNIQUE3
586 
587 #undef optional_ALIGN_TYPE
588 
589 #elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
590 
591 // Use user-specified type for alignment:
592 
593 #define optional_ALIGN_AS( unused ) \
594  optional_CONFIG_ALIGN_AS
595 
596 #else // optional_CONFIG_MAX_ALIGN_HACK
597 
598 // Determine POD type to use for alignment:
599 
600 #define optional_ALIGN_AS( to_align ) \
601  typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
602 
603 template< typename T >
604 struct alignment_of;
605 
606 template< typename T >
608 {
609  char c;
610  T t;
612 };
613 
614 template< size_t A, size_t S >
616 {
617  enum { value = A < S ? A : S };
618 };
619 
620 template< typename T >
622 {
623  enum { value = alignment_logic<
624  sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
625 };
626 
627 template< typename List, size_t N >
629 {
630  typedef typename std11::conditional<
631  N == sizeof( typename List::head ),
632  typename List::head,
633  typename type_of_size<typename List::tail, N >::type >::type type;
634 };
635 
636 template< size_t N >
637 struct type_of_size< nulltype, N >
638 {
639  typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
640 };
641 
642 template< typename T>
643 struct struct_t { T _; };
644 
645 #define optional_ALIGN_TYPE( type ) \
646  typelist< type , typelist< struct_t< type >
647 
648 struct Unknown;
649 
650 typedef
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( char *),
660  optional_ALIGN_TYPE( short * ),
661  optional_ALIGN_TYPE( int * ),
662  optional_ALIGN_TYPE( long * ),
663  optional_ALIGN_TYPE( float * ),
664  optional_ALIGN_TYPE( double * ),
665  optional_ALIGN_TYPE( long double * ),
666 
667  optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
668  optional_ALIGN_TYPE( Unknown * Unknown::* ),
669  optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
670 
671  nulltype
672  > > > > > > > > > > > > > >
673  > > > > > > > > > > > > > >
674  > > > > > >
676 
677 #undef optional_ALIGN_TYPE
678 
679 #endif // optional_CONFIG_MAX_ALIGN_HACK
680 
682 
683 template< typename T >
685 {
686 //private:
687 // template< typename > friend class optional;
688 
689  typedef T value_type;
690 
691  storage_t() optional_is_default
692 
693  explicit storage_t( value_type const & v )
694  {
695  construct_value( v );
696  }
697 
698  void construct_value( value_type const & v )
699  {
700  ::new( value_ptr() ) value_type( v );
701  }
702 
703 #if optional_CPP11_OR_GREATER
704 
705  explicit storage_t( value_type && v )
706  {
707  construct_value( std::move( v ) );
708  }
709 
710  void construct_value( value_type && v )
711  {
712  ::new( value_ptr() ) value_type( std::move( v ) );
713  }
714 
715  template< class... Args >
716  void emplace( Args&&... args )
717  {
718  ::new( value_ptr() ) value_type( std::forward<Args>(args)... );
719  }
720 
721  template< class U, class... Args >
722  void emplace( std::initializer_list<U> il, Args&&... args )
723  {
724  ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... );
725  }
726 
727 #endif
728 
729  void destruct_value()
730  {
731  value_ptr()->~T();
732  }
733 
734  optional_nodiscard value_type const * value_ptr() const
735  {
736  return as<value_type>();
737  }
738 
739  value_type * value_ptr()
740  {
741  return as<value_type>();
742  }
743 
744  optional_nodiscard value_type const & value() const optional_ref_qual
745  {
746  return * value_ptr();
747  }
748 
749  value_type & value() optional_ref_qual
750  {
751  return * value_ptr();
752  }
753 
754 #if optional_HAVE( REF_QUALIFIER )
755 
756  optional_nodiscard value_type const && value() const optional_refref_qual
757  {
758  return std::move( value() );
759  }
760 
761  value_type && value() optional_refref_qual
762  {
763  return std::move( value() );
764  }
765 
766 #endif
767 
768 #if optional_CPP11_OR_GREATER
769 
770  using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
771  aligned_storage_t data;
772 
773 #elif optional_CONFIG_MAX_ALIGN_HACK
774 
775  typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
776 
777  max_align_t hack;
778  aligned_storage_t data;
779 
780 #else
781  typedef optional_ALIGN_AS(value_type) align_as_type;
782 
783  typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
784  aligned_storage_t data;
785 
786 # undef optional_ALIGN_AS
787 
788 #endif // optional_CONFIG_MAX_ALIGN_HACK
789 
790  optional_nodiscard void * ptr() optional_noexcept
791  {
792  return &data;
793  }
794 
795  optional_nodiscard void const * ptr() const optional_noexcept
796  {
797  return &data;
798  }
799 
800  template <typename U>
801  optional_nodiscard U * as()
802  {
803  return reinterpret_cast<U*>( ptr() );
804  }
805 
806  template <typename U>
807  optional_nodiscard U const * as() const
808  {
809  return reinterpret_cast<U const *>( ptr() );
810  }
811 };
812 
813 } // namespace detail
814 
816 
817 struct nullopt_t
818 {
819  struct init{};
820  explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
821 };
822 
823 #if optional_HAVE( CONSTEXPR_11 )
824 constexpr nullopt_t nullopt{ nullopt_t::init{} };
825 #else
826 // extra parenthesis to prevent the most vexing parse:
827 const nullopt_t nullopt(( nullopt_t::init() ));
828 #endif
829 
831 
832 #if ! optional_CONFIG_NO_EXCEPTIONS
833 
834 class bad_optional_access : public std::logic_error
835 {
836 public:
837  explicit bad_optional_access()
838  : logic_error( "bad optional access" ) {}
839 };
840 
841 #endif //optional_CONFIG_NO_EXCEPTIONS
842 
844 
845 template< typename T>
846 class optional
847 {
848 private:
849  template< typename > friend class optional;
850 
851  typedef void (optional::*safe_bool)() const;
852 
853 public:
854  typedef T value_type;
855 
856  // x.x.3.1, constructors
857 
858  // 1a - default construct
859  optional_constexpr optional() optional_noexcept
860  : has_value_( false )
861  , contained()
862  {}
863 
864  // 1b - construct explicitly empty
865  // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
866  optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept
867  : has_value_( false )
868  , contained()
869  {}
870 
871  // 2 - copy-construct
872 #if optional_CPP11_OR_GREATER
873  // template< typename U = T
874  // optional_REQUIRES_T(
875  // std::is_copy_constructible<U>::value
876  // || std11::is_trivially_copy_constructible<U>::value
877  // )
878  // >
879 #endif
880  optional_constexpr14 optional( optional const & other )
881  : has_value_( other.has_value() )
882  {
883  if ( other.has_value() )
884  {
885  contained.construct_value( other.contained.value() );
886  }
887  }
888 
889 #if optional_CPP11_OR_GREATER
890 
891  // 3 (C++11) - move-construct from optional
892  template< typename U = T
893  optional_REQUIRES_T(
894  std::is_move_constructible<U>::value
895  || std11::is_trivially_move_constructible<U>::value
896  )
897  >
898  optional_constexpr14 optional( optional && other )
899  // NOLINTNEXTLINE( performance-noexcept-move-constructor )
900  noexcept( std::is_nothrow_move_constructible<T>::value )
901  : has_value_( other.has_value() )
902  {
903  if ( other.has_value() )
904  {
905  contained.construct_value( std::move( other.contained.value() ) );
906  }
907  }
908 
909  // 4a (C++11) - explicit converting copy-construct from optional
910  template< typename U
911  optional_REQUIRES_T(
912  std::is_constructible<T, U const &>::value
913  && !std::is_constructible<T, optional<U> & >::value
914  && !std::is_constructible<T, optional<U> && >::value
915  && !std::is_constructible<T, optional<U> const & >::value
916  && !std::is_constructible<T, optional<U> const && >::value
917  && !std::is_convertible< optional<U> & , T>::value
918  && !std::is_convertible< optional<U> && , T>::value
919  && !std::is_convertible< optional<U> const & , T>::value
920  && !std::is_convertible< optional<U> const &&, T>::value
921  && !std::is_convertible< U const & , T>::value /*=> explicit */
922  )
923  >
924  explicit optional( optional<U> const & other )
925  : has_value_( other.has_value() )
926  {
927  if ( other.has_value() )
928  {
929  contained.construct_value( T{ other.contained.value() } );
930  }
931  }
932 #endif // optional_CPP11_OR_GREATER
933 
934  // 4b (C++98 and later) - non-explicit converting copy-construct from optional
935  template< typename U
936 #if optional_CPP11_OR_GREATER
937  optional_REQUIRES_T(
938  std::is_constructible<T, U const &>::value
939  && !std::is_constructible<T, optional<U> & >::value
940  && !std::is_constructible<T, optional<U> && >::value
941  && !std::is_constructible<T, optional<U> const & >::value
942  && !std::is_constructible<T, optional<U> const && >::value
943  && !std::is_convertible< optional<U> & , T>::value
944  && !std::is_convertible< optional<U> && , T>::value
945  && !std::is_convertible< optional<U> const & , T>::value
946  && !std::is_convertible< optional<U> const &&, T>::value
947  && std::is_convertible< U const & , T>::value /*=> non-explicit */
948  )
949 #endif // optional_CPP11_OR_GREATER
950  >
951  // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
952  /*non-explicit*/ optional( optional<U> const & other )
953  : has_value_( other.has_value() )
954  {
955  if ( other.has_value() )
956  {
957  contained.construct_value( other.contained.value() );
958  }
959  }
960 
961 #if optional_CPP11_OR_GREATER
962 
963  // 5a (C++11) - explicit converting move-construct from optional
964  template< typename U
965  optional_REQUIRES_T(
966  std::is_constructible<T, U &&>::value
967  && !std::is_constructible<T, optional<U> & >::value
968  && !std::is_constructible<T, optional<U> && >::value
969  && !std::is_constructible<T, optional<U> const & >::value
970  && !std::is_constructible<T, optional<U> const && >::value
971  && !std::is_convertible< optional<U> & , T>::value
972  && !std::is_convertible< optional<U> && , T>::value
973  && !std::is_convertible< optional<U> const & , T>::value
974  && !std::is_convertible< optional<U> const &&, T>::value
975  && !std::is_convertible< U &&, T>::value /*=> explicit */
976  )
977  >
978  explicit optional( optional<U> && other
979  )
980  : has_value_( other.has_value() )
981  {
982  if ( other.has_value() )
983  {
984  contained.construct_value( T{ std::move( other.contained.value() ) } );
985  }
986  }
987 
988  // 5a (C++11) - non-explicit converting move-construct from optional
989  template< typename U
990  optional_REQUIRES_T(
991  std::is_constructible<T, U &&>::value
992  && !std::is_constructible<T, optional<U> & >::value
993  && !std::is_constructible<T, optional<U> && >::value
994  && !std::is_constructible<T, optional<U> const & >::value
995  && !std::is_constructible<T, optional<U> const && >::value
996  && !std::is_convertible< optional<U> & , T>::value
997  && !std::is_convertible< optional<U> && , T>::value
998  && !std::is_convertible< optional<U> const & , T>::value
999  && !std::is_convertible< optional<U> const &&, T>::value
1000  && std::is_convertible< U &&, T>::value /*=> non-explicit */
1001  )
1002  >
1003  // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1004  /*non-explicit*/ optional( optional<U> && other )
1005  : has_value_( other.has_value() )
1006  {
1007  if ( other.has_value() )
1008  {
1009  contained.construct_value( std::move( other.contained.value() ) );
1010  }
1011  }
1012 
1013  // 6 (C++11) - in-place construct
1014  template< typename... Args
1015  optional_REQUIRES_T(
1016  std::is_constructible<T, Args&&...>::value
1017  )
1018  >
1019  optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
1020  : has_value_( true )
1021  , contained( T( std::forward<Args>(args)...) )
1022  {}
1023 
1024  // 7 (C++11) - in-place construct, initializer-list
1025  template< typename U, typename... Args
1026  optional_REQUIRES_T(
1027  std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1028  )
1029  >
1030  optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
1031  : has_value_( true )
1032  , contained( T( il, std::forward<Args>(args)...) )
1033  {}
1034 
1035  // 8a (C++11) - explicit move construct from value
1036  template< typename U = T
1037  optional_REQUIRES_T(
1038  std::is_constructible<T, U&&>::value
1039  && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1040  && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1041  && !std::is_convertible<U&&, T>::value /*=> explicit */
1042  )
1043  >
1044  optional_constexpr explicit optional( U && value )
1045  : has_value_( true )
1046  , contained( T{ std::forward<U>( value ) } )
1047  {}
1048 
1049  // 8b (C++11) - non-explicit move construct from value
1050  template< typename U = T
1051  optional_REQUIRES_T(
1052  std::is_constructible<T, U&&>::value
1053  && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1054  && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1055  && std::is_convertible<U&&, T>::value /*=> non-explicit */
1056  )
1057  >
1058  // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
1059  optional_constexpr /*non-explicit*/ optional( U && value )
1060  : has_value_( true )
1061  , contained( std::forward<U>( value ) )
1062  {}
1063 
1064 #else // optional_CPP11_OR_GREATER
1065 
1066  // 8 (C++98)
1067  optional( value_type const & value )
1068  : has_value_( true )
1069  , contained( value )
1070  {}
1071 
1072 #endif // optional_CPP11_OR_GREATER
1073 
1074  // x.x.3.2, destructor
1075 
1076  ~optional()
1077  {
1078  if ( has_value() )
1079  {
1080  contained.destruct_value();
1081  }
1082  }
1083 
1084  // x.x.3.3, assignment
1085 
1086  // 1 (C++98and later) - assign explicitly empty
1087  optional & operator=( nullopt_t /*unused*/) optional_noexcept
1088  {
1089  reset();
1090  return *this;
1091  }
1092 
1093  // 2 (C++98and later) - copy-assign from optional
1094 #if optional_CPP11_OR_GREATER
1095  // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1096  optional_REQUIRES_R(
1097  optional &,
1098  true
1099 // std::is_copy_constructible<T>::value
1100 // && std::is_copy_assignable<T>::value
1101  )
1102  operator=( optional const & other )
1103  noexcept(
1104  std::is_nothrow_move_assignable<T>::value
1105  && std::is_nothrow_move_constructible<T>::value
1106  )
1107 #else
1108  optional & operator=( optional const & other )
1109 #endif
1110  {
1111  if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
1112  else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); }
1113  else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; }
1114  return *this;
1115  }
1116 
1117 #if optional_CPP11_OR_GREATER
1118 
1119  // 3 (C++11) - move-assign from optional
1120  // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1121  optional_REQUIRES_R(
1122  optional &,
1123  true
1124 // std::is_move_constructible<T>::value
1125 // && std::is_move_assignable<T>::value
1126  )
1127  operator=( optional && other ) noexcept
1128  {
1129  if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
1130  else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); }
1131  else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); }
1132  return *this;
1133  }
1134 
1135  // 4 (C++11) - move-assign from value
1136  template< typename U = T >
1137  // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1138  optional_REQUIRES_R(
1139  optional &,
1140  std::is_constructible<T , U>::value
1141  && std::is_assignable<T&, U>::value
1142  && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1143  && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
1144  && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
1145  )
1146  operator=( U && value )
1147  {
1148  if ( has_value() )
1149  {
1150  contained.value() = std::forward<U>( value );
1151  }
1152  else
1153  {
1154  initialize( T( std::forward<U>( value ) ) );
1155  }
1156  return *this;
1157  }
1158 
1159 #else // optional_CPP11_OR_GREATER
1160 
1161  // 4 (C++98) - copy-assign from value
1162  template< typename U /*= T*/ >
1163  optional & operator=( U const & value )
1164  {
1165  if ( has_value() ) contained.value() = value;
1166  else initialize( T( value ) );
1167  return *this;
1168  }
1169 
1170 #endif // optional_CPP11_OR_GREATER
1171 
1172  // 5 (C++98 and later) - converting copy-assign from optional
1173  template< typename U >
1174 #if optional_CPP11_OR_GREATER
1175  // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1176  optional_REQUIRES_R(
1177  optional&,
1178  std::is_constructible< T , U const &>::value
1179  && std::is_assignable< T&, U const &>::value
1180  && !std::is_constructible<T, optional<U> & >::value
1181  && !std::is_constructible<T, optional<U> && >::value
1182  && !std::is_constructible<T, optional<U> const & >::value
1183  && !std::is_constructible<T, optional<U> const && >::value
1184  && !std::is_convertible< optional<U> & , T>::value
1185  && !std::is_convertible< optional<U> && , T>::value
1186  && !std::is_convertible< optional<U> const & , T>::value
1187  && !std::is_convertible< optional<U> const &&, T>::value
1188  && !std::is_assignable< T&, optional<U> & >::value
1189  && !std::is_assignable< T&, optional<U> && >::value
1190  && !std::is_assignable< T&, optional<U> const & >::value
1191  && !std::is_assignable< T&, optional<U> const && >::value
1192  )
1193 #else
1194  optional&
1195 #endif // optional_CPP11_OR_GREATER
1196  operator=( optional<U> const & other )
1197  {
1198  return *this = optional( other );
1199  }
1200 
1201 #if optional_CPP11_OR_GREATER
1202 
1203  // 6 (C++11) - converting move-assign from optional
1204  template< typename U >
1205  // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
1206  optional_REQUIRES_R(
1207  optional&,
1208  std::is_constructible< T , U>::value
1209  && std::is_assignable< T&, U>::value
1210  && !std::is_constructible<T, optional<U> & >::value
1211  && !std::is_constructible<T, optional<U> && >::value
1212  && !std::is_constructible<T, optional<U> const & >::value
1213  && !std::is_constructible<T, optional<U> const && >::value
1214  && !std::is_convertible< optional<U> & , T>::value
1215  && !std::is_convertible< optional<U> && , T>::value
1216  && !std::is_convertible< optional<U> const & , T>::value
1217  && !std::is_convertible< optional<U> const &&, T>::value
1218  && !std::is_assignable< T&, optional<U> & >::value
1219  && !std::is_assignable< T&, optional<U> && >::value
1220  && !std::is_assignable< T&, optional<U> const & >::value
1221  && !std::is_assignable< T&, optional<U> const && >::value
1222  )
1223  operator=( optional<U> && other )
1224  {
1225  return *this = optional( std::move( other ) );
1226  }
1227 
1228  // 7 (C++11) - emplace
1229  template< typename... Args
1230  optional_REQUIRES_T(
1231  std::is_constructible<T, Args&&...>::value
1232  )
1233  >
1234  T& emplace( Args&&... args )
1235  {
1236  *this = nullopt;
1237  contained.emplace( std::forward<Args>(args)... );
1238  has_value_ = true;
1239  return contained.value();
1240  }
1241 
1242  // 8 (C++11) - emplace, initializer-list
1243  template< typename U, typename... Args
1244  optional_REQUIRES_T(
1245  std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1246  )
1247  >
1248  T& emplace( std::initializer_list<U> il, Args&&... args )
1249  {
1250  *this = nullopt;
1251  contained.emplace( il, std::forward<Args>(args)... );
1252  has_value_ = true;
1253  return contained.value();
1254  }
1255 
1256 #endif // optional_CPP11_OR_GREATER
1257 
1258  // x.x.3.4, swap
1259 
1260  void swap( optional & other )
1261 #if optional_CPP11_OR_GREATER
1262  noexcept(
1263  std::is_nothrow_move_constructible<T>::value
1264  && std17::is_nothrow_swappable<T>::value
1265  )
1266 #endif
1267  {
1268  using std::swap;
1269  if ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); }
1270  else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); }
1271  else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); }
1272  }
1273 
1274  // x.x.3.5, observers
1275 
1276  optional_constexpr value_type const * operator ->() const
1277  {
1278  return assert( has_value() ),
1279  contained.value_ptr();
1280  }
1281 
1282  optional_constexpr14 value_type * operator ->()
1283  {
1284  return assert( has_value() ),
1285  contained.value_ptr();
1286  }
1287 
1288  optional_constexpr value_type const & operator *() const optional_ref_qual
1289  {
1290  return assert( has_value() ),
1291  contained.value();
1292  }
1293 
1294  optional_constexpr14 value_type & operator *() optional_ref_qual
1295  {
1296  return assert( has_value() ),
1297  contained.value();
1298  }
1299 
1300 #if optional_HAVE( REF_QUALIFIER )
1301 
1302  optional_constexpr value_type const && operator *() const optional_refref_qual
1303  {
1304  return std::move( **this );
1305  }
1306 
1307  optional_constexpr14 value_type && operator *() optional_refref_qual
1308  {
1309  return std::move( **this );
1310  }
1311 
1312 #endif
1313 
1314 #if optional_CPP11_OR_GREATER
1315  optional_constexpr explicit operator bool() const optional_noexcept
1316  {
1317  return has_value();
1318  }
1319 #else
1320  optional_constexpr operator safe_bool() const optional_noexcept
1321  {
1322  return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
1323  }
1324 #endif
1325 
1326  // NOLINTNEXTLINE( modernize-use-nodiscard )
1327  /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept
1328  {
1329  return has_value_;
1330  }
1331 
1332  // NOLINTNEXTLINE( modernize-use-nodiscard )
1333  /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual
1334  {
1335 #if optional_CONFIG_NO_EXCEPTIONS
1336  assert( has_value() );
1337 #else
1338  if ( ! has_value() )
1339  {
1340  throw bad_optional_access();
1341  }
1342 #endif
1343  return contained.value();
1344  }
1345 
1346  optional_constexpr14 value_type & value() optional_ref_qual
1347  {
1348 #if optional_CONFIG_NO_EXCEPTIONS
1349  assert( has_value() );
1350 #else
1351  if ( ! has_value() )
1352  {
1353  throw bad_optional_access();
1354  }
1355 #endif
1356  return contained.value();
1357  }
1358 
1359 #if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )
1360 
1361  // NOLINTNEXTLINE( modernize-use-nodiscard )
1362  /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual
1363  {
1364  return std::move( value() );
1365  }
1366 
1367  optional_constexpr14 value_type && value() optional_refref_qual
1368  {
1369  return std::move( value() );
1370  }
1371 
1372 #endif
1373 
1374 #if optional_CPP11_OR_GREATER
1375 
1376  template< typename U >
1377  optional_constexpr value_type value_or( U && v ) const optional_ref_qual
1378  {
1379  return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
1380  }
1381 
1382  template< typename U >
1383  optional_constexpr14 value_type value_or( U && v ) optional_refref_qual
1384  {
1385  return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
1386  }
1387 
1388 #else
1389 
1390  template< typename U >
1391  optional_constexpr value_type value_or( U const & v ) const
1392  {
1393  return has_value() ? contained.value() : static_cast<value_type>( v );
1394  }
1395 
1396 #endif // optional_CPP11_OR_GREATER
1397 
1398  // x.x.3.6, modifiers
1399 
1400  void reset() optional_noexcept
1401  {
1402  if ( has_value() )
1403  {
1404  contained.destruct_value();
1405  }
1406 
1407  has_value_ = false;
1408  }
1409 
1410 private:
1411  void this_type_does_not_support_comparisons() const {}
1412 
1413  template< typename V >
1414  void initialize( V const & value )
1415  {
1416  assert( ! has_value() );
1417  contained.construct_value( value );
1418  has_value_ = true;
1419  }
1420 
1421 #if optional_CPP11_OR_GREATER
1422  template< typename V >
1423  void initialize( V && value )
1424  {
1425  assert( ! has_value() );
1426  contained.construct_value( std::move( value ) );
1427  has_value_ = true;
1428  }
1429 
1430 #endif
1431 
1432 private:
1433  bool has_value_;
1435 
1436 };
1437 
1438 // Relational operators
1439 
1440 template< typename T, typename U >
1441 inline optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
1442 {
1443  return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
1444 }
1445 
1446 template< typename T, typename U >
1447 inline optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
1448 {
1449  return !(x == y);
1450 }
1451 
1452 template< typename T, typename U >
1453 inline optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
1454 {
1455  return (!y) ? false : (!x) ? true : *x < *y;
1456 }
1457 
1458 template< typename T, typename U >
1459 inline optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
1460 {
1461  return (y < x);
1462 }
1463 
1464 template< typename T, typename U >
1465 inline optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
1466 {
1467  return !(y < x);
1468 }
1469 
1470 template< typename T, typename U >
1471 inline optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
1472 {
1473  return !(x < y);
1474 }
1475 
1476 // Comparison with nullopt
1477 
1478 template< typename T >
1479 inline optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1480 {
1481  return (!x);
1482 }
1483 
1484 template< typename T >
1485 inline optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1486 {
1487  return (!x);
1488 }
1489 
1490 template< typename T >
1491 inline optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1492 {
1493  return bool(x);
1494 }
1495 
1496 template< typename T >
1497 inline optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1498 {
1499  return bool(x);
1500 }
1501 
1502 template< typename T >
1503 inline optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1504 {
1505  return false;
1506 }
1507 
1508 template< typename T >
1509 inline optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1510 {
1511  return bool(x);
1512 }
1513 
1514 template< typename T >
1515 inline optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1516 {
1517  return (!x);
1518 }
1519 
1520 template< typename T >
1521 inline optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1522 {
1523  return true;
1524 }
1525 
1526 template< typename T >
1527 inline optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1528 {
1529  return bool(x);
1530 }
1531 
1532 template< typename T >
1533 inline optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1534 {
1535  return false;
1536 }
1537 
1538 template< typename T >
1539 inline optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1540 {
1541  return true;
1542 }
1543 
1544 template< typename T >
1545 inline optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1546 {
1547  return (!x);
1548 }
1549 
1550 // Comparison with T
1551 
1552 template< typename T, typename U >
1553 inline optional_constexpr bool operator==( optional<T> const & x, U const & v )
1554 {
1555  return bool(x) ? *x == v : false;
1556 }
1557 
1558 template< typename T, typename U >
1559 inline optional_constexpr bool operator==( U const & v, optional<T> const & x )
1560 {
1561  return bool(x) ? v == *x : false;
1562 }
1563 
1564 template< typename T, typename U >
1565 inline optional_constexpr bool operator!=( optional<T> const & x, U const & v )
1566 {
1567  return bool(x) ? *x != v : true;
1568 }
1569 
1570 template< typename T, typename U >
1571 inline optional_constexpr bool operator!=( U const & v, optional<T> const & x )
1572 {
1573  return bool(x) ? v != *x : true;
1574 }
1575 
1576 template< typename T, typename U >
1577 inline optional_constexpr bool operator<( optional<T> const & x, U const & v )
1578 {
1579  return bool(x) ? *x < v : true;
1580 }
1581 
1582 template< typename T, typename U >
1583 inline optional_constexpr bool operator<( U const & v, optional<T> const & x )
1584 {
1585  return bool(x) ? v < *x : false;
1586 }
1587 
1588 template< typename T, typename U >
1589 inline optional_constexpr bool operator<=( optional<T> const & x, U const & v )
1590 {
1591  return bool(x) ? *x <= v : true;
1592 }
1593 
1594 template< typename T, typename U >
1595 inline optional_constexpr bool operator<=( U const & v, optional<T> const & x )
1596 {
1597  return bool(x) ? v <= *x : false;
1598 }
1599 
1600 template< typename T, typename U >
1601 inline optional_constexpr bool operator>( optional<T> const & x, U const & v )
1602 {
1603  return bool(x) ? *x > v : false;
1604 }
1605 
1606 template< typename T, typename U >
1607 inline optional_constexpr bool operator>( U const & v, optional<T> const & x )
1608 {
1609  return bool(x) ? v > *x : true;
1610 }
1611 
1612 template< typename T, typename U >
1613 inline optional_constexpr bool operator>=( optional<T> const & x, U const & v )
1614 {
1615  return bool(x) ? *x >= v : false;
1616 }
1617 
1618 template< typename T, typename U >
1619 inline optional_constexpr bool operator>=( U const & v, optional<T> const & x )
1620 {
1621  return bool(x) ? v >= *x : true;
1622 }
1623 
1624 // Specialized algorithms
1625 
1626 template< typename T
1627 #if optional_CPP11_OR_GREATER
1628  optional_REQUIRES_T(
1629  std::is_move_constructible<T>::value
1630  && std17::is_swappable<T>::value )
1631 #endif
1632 >
1633 void swap( optional<T> & x, optional<T> & y )
1634 #if optional_CPP11_OR_GREATER
1635  noexcept( noexcept( x.swap(y) ) )
1636 #endif
1637 {
1638  x.swap( y );
1639 }
1640 
1641 #if optional_CPP11_OR_GREATER
1642 
1643 template< typename T >
1644 optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value )
1645 {
1646  return optional< typename std::decay<T>::type >( std::forward<T>( value ) );
1647 }
1648 
1649 template< typename T, typename...Args >
1650 optional_constexpr optional<T> make_optional( Args&&... args )
1651 {
1652  return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
1653 }
1654 
1655 template< typename T, typename U, typename... Args >
1656 optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
1657 {
1658  return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
1659 }
1660 
1661 #else
1662 
1663 template< typename T >
1664 optional<T> make_optional( T const & value )
1665 {
1666  return optional<T>( value );
1667 }
1668 
1669 #endif // optional_CPP11_OR_GREATER
1670 
1671 } // namespace optional_lite
1672 
1673 using optional_lite::optional;
1674 using optional_lite::nullopt_t;
1675 using optional_lite::nullopt;
1676 
1677 #if ! optional_CONFIG_NO_EXCEPTIONS
1678 using optional_lite::bad_optional_access;
1679 #endif
1680 
1681 using optional_lite::make_optional;
1682 
1683 } // namespace nonstd
1684 
1685 #if optional_CPP11_OR_GREATER
1686 
1687 // specialize the std::hash algorithm:
1688 
1689 namespace std {
1690 
1691 template< class T >
1692 struct hash< nonstd::optional<T> >
1693 {
1694 public:
1695  std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
1696  {
1697  return bool( v ) ? std::hash<T>{}( *v ) : 0;
1698  }
1699 };
1700 
1701 } //namespace std
1702 
1703 #endif // optional_CPP11_OR_GREATER
1704 
1705 #if defined(__clang__)
1706 # pragma clang diagnostic pop
1707 #elif defined(__GNUC__)
1708 # pragma GCC diagnostic pop
1709 #elif defined(_MSC_VER )
1710 # pragma warning( pop )
1711 #endif
1712 
1713 #endif // optional_USES_STD_OPTIONAL
1714 
1715 #endif // NONSTD_OPTIONAL_LITE_HPP
class optional
Definition: optional.hpp:847
Definition: optional.hpp:122
Definition: optional.hpp:119
Definition: optional.hpp:126
Definition: optional.hpp:527
Definition: optional.hpp:643
Definition: optional.hpp:531
Definition: optional.hpp:819
disengaged state tag
Definition: optional.hpp:818
Definition: optional.hpp:431
C++03 constructed union to hold value.
Definition: optional.hpp:685