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