cpp-common/vendor/optional-lite: bump to 3.6.0
[babeltrace.git] / src / cpp-common / vendor / optional-lite / optional.hpp
CommitLineData
dba85559
PP
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
008797c3 15#define optional_lite_MINOR 6
dba85559
PP
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
008797c3 59# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS))
dba85559
PP
60# define optional_CONFIG_NO_EXCEPTIONS 0
61# else
62# define optional_CONFIG_NO_EXCEPTIONS 1
63# endif
64#endif
65
008797c3 66// C++ language version detection (C++23 is speculative):
dba85559
PP
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 )
008797c3
PP
82#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202002L )
83#define optional_CPP23_OR_GREATER ( optional_CPLUSPLUS >= 202300L )
dba85559
PP
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
116namespace nonstd {
117
118using std::in_place;
119using std::in_place_type;
120using std::in_place_index;
121using std::in_place_t;
122using std::in_place_type_t;
123using 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
139namespace nonstd {
140namespace detail {
141
142template< class T >
143struct in_place_type_tag {};
144
145template< std::size_t K >
146struct in_place_index_tag {};
147
148} // namespace detail
149
150struct in_place_t {};
151
152template< class T >
153inline 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
158template< std::size_t K >
159inline 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
164template< class T >
165inline 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
170template< std::size_t K >
171inline 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
199namespace 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
466namespace nonstd { namespace optional_lite {
467
468namespace std11 {
469
470template< class T, T v > struct integral_constant { enum { value = v }; };
471template< bool B > struct bool_constant : integral_constant<bool, B>{};
472
473typedef bool_constant< true > true_type;
474typedef 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
531namespace std17 {
532
533#if optional_CPP17_OR_GREATER
534
535using std::is_swappable;
536using std::is_nothrow_swappable;
537
538#elif optional_CPP11_OR_GREATER
539
540namespace detail {
541
542using std::swap;
543
544struct 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
553struct 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
574template< typename T >
575struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
576
577template< typename T >
578struct 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
586namespace std20 {
587
588template< typename T >
589struct 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
600template< typename T >
601class optional;
602
603namespace detail {
604
605// C++11 emulation:
606
607struct nulltype{};
608
609template< typename Head, typename Tail >
610struct 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
627template< typename T >
628struct struct_t { T _; };
629
630union 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
683template< typename T >
684struct alignment_of;
685
686template< typename T >
687struct alignment_of_hack
688{
689 char c;
690 T t;
691 alignment_of_hack();
692};
693
694template< size_t A, size_t S >
695struct alignment_logic
696{
697 enum { value = A < S ? A : S };
698};
699
700template< typename T >
701struct alignment_of
702{
703 enum { value = alignment_logic<
704 sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
705};
706
707template< typename List, size_t N >
708struct 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
716template< size_t N >
717struct type_of_size< nulltype, N >
718{
719 typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
720};
721
722template< typename T>
723struct struct_t { T _; };
724
725#define optional_ALIGN_TYPE( type ) \
726 typelist< type , typelist< struct_t< type >
727
728struct Unknown;
729
730typedef
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
763template< typename T >
764union 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 {
008797c3 792 ::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( std::move( v ) );
dba85559
PP
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 {
008797c3 804 ::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( std::forward<Args>(args)... );
dba85559
PP
805 }
806
807 template< class U, class... Args >
808 void emplace( std::initializer_list<U> il, Args&&... args )
809 {
008797c3 810 ::new( const_cast<void *>(static_cast<const volatile void *>(value_ptr())) ) value_type( il, std::forward<Args>(args)... );
dba85559
PP
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
903struct nullopt_t
904{
905 struct init{};
906 explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
907};
908
909#if optional_HAVE( CONSTEXPR_11 )
910constexpr nullopt_t nullopt{ nullopt_t::init{} };
911#else
912// extra parenthesis to prevent the most vexing parse:
913const nullopt_t nullopt(( nullopt_t::init() ));
914#endif
915
916/// optional access error
917
918#if ! optional_CONFIG_NO_EXCEPTIONS
919
920class bad_optional_access : public std::logic_error
921{
922public:
923 explicit bad_optional_access()
924 : logic_error( "bad optional access" ) {}
925};
926
927#endif //optional_CONFIG_NO_EXCEPTIONS
928
929/// optional
930
931template< typename T>
932class 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
943private:
944 template< typename > friend class optional;
945
946 typedef void (optional::*safe_bool)() const;
947
948public:
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
1542private:
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() );
008797c3 1558 contained.construct_value( std::forward<V>( value ) );
dba85559
PP
1559 has_value_ = true;
1560 }
1561
1562#endif
1563
1564private:
1565 bool has_value_;
1566 detail::storage_t< value_type > contained;
1567
1568};
1569
1570// Relational operators
1571
1572template< typename T, typename U >
1573optional_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
1578template< typename T, typename U >
1579optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
1580{
1581 return !(x == y);
1582}
1583
1584template< typename T, typename U >
1585optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
1586{
1587 return (!y) ? false : (!x) ? true : *x < *y;
1588}
1589
1590template< typename T, typename U >
1591optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
1592{
1593 return (y < x);
1594}
1595
1596template< typename T, typename U >
1597optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
1598{
1599 return !(y < x);
1600}
1601
1602template< typename T, typename U >
1603optional_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
1610template< typename T >
1611optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1612{
1613 return (!x);
1614}
1615
1616template< typename T >
1617optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1618{
1619 return (!x);
1620}
1621
1622template< typename T >
1623optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1624{
1625 return bool(x);
1626}
1627
1628template< typename T >
1629optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1630{
1631 return bool(x);
1632}
1633
1634template< typename T >
1635optional_nodiscard optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1636{
1637 return false;
1638}
1639
1640template< typename T >
1641optional_nodiscard optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
1642{
1643 return bool(x);
1644}
1645
1646template< typename T >
1647optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1648{
1649 return (!x);
1650}
1651
1652template< typename T >
1653optional_nodiscard optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1654{
1655 return true;
1656}
1657
1658template< typename T >
1659optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
1660{
1661 return bool(x);
1662}
1663
1664template< typename T >
1665optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
1666{
1667 return false;
1668}
1669
1670template< typename T >
1671optional_nodiscard optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
1672{
1673 return true;
1674}
1675
1676template< typename T >
1677optional_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
1684template< typename T, typename U >
1685optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, U const & v )
1686{
1687 return bool(x) ? *x == v : false;
1688}
1689
1690template< typename T, typename U >
1691optional_nodiscard optional_constexpr bool operator==( U const & v, optional<T> const & x )
1692{
1693 return bool(x) ? v == *x : false;
1694}
1695
1696template< typename T, typename U >
1697optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, U const & v )
1698{
1699 return bool(x) ? *x != v : true;
1700}
1701
1702template< typename T, typename U >
1703optional_nodiscard optional_constexpr bool operator!=( U const & v, optional<T> const & x )
1704{
1705 return bool(x) ? v != *x : true;
1706}
1707
1708template< typename T, typename U >
1709optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, U const & v )
1710{
1711 return bool(x) ? *x < v : true;
1712}
1713
1714template< typename T, typename U >
1715optional_nodiscard optional_constexpr bool operator<( U const & v, optional<T> const & x )
1716{
1717 return bool(x) ? v < *x : false;
1718}
1719
1720template< typename T, typename U >
1721optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, U const & v )
1722{
1723 return bool(x) ? *x <= v : true;
1724}
1725
1726template< typename T, typename U >
1727optional_nodiscard optional_constexpr bool operator<=( U const & v, optional<T> const & x )
1728{
1729 return bool(x) ? v <= *x : false;
1730}
1731
1732template< typename T, typename U >
1733optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, U const & v )
1734{
1735 return bool(x) ? *x > v : false;
1736}
1737
1738template< typename T, typename U >
1739optional_nodiscard optional_constexpr bool operator>( U const & v, optional<T> const & x )
1740{
1741 return bool(x) ? v > *x : true;
1742}
1743
1744template< typename T, typename U >
1745optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, U const & v )
1746{
1747 return bool(x) ? *x >= v : false;
1748}
1749
1750template< typename T, typename U >
1751optional_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
1758template< 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>
1765void 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
1775template< typename T >
1776optional_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
1781template< typename T, typename...Args >
1782optional_constexpr optional<T> make_optional( Args&&... args )
1783{
1784 return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
1785}
1786
1787template< typename T, typename U, typename... Args >
1788optional_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
1795template< typename T >
1796optional<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
1805using optional_lite::optional;
1806using optional_lite::nullopt_t;
1807using optional_lite::nullopt;
1808
1809#if ! optional_CONFIG_NO_EXCEPTIONS
1810using optional_lite::bad_optional_access;
1811#endif
1812
1813using optional_lite::make_optional;
1814
1815} // namespace nonstd
1816
1817#if optional_CPP11_OR_GREATER
1818
1819// specialize the std::hash algorithm:
1820
1821namespace std {
1822
1823template< class T >
1824struct hash< nonstd::optional<T> >
1825{
1826public:
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.099748 seconds and 4 git commands to generate.