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