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