blob: 08c78abede8a90b96b9fb02a0bb0c942f4211508 [file] [log] [blame]
Davide Pesavento17b61b42018-11-21 23:10:48 -05001// Copyright 2016-2018 by Martin Moene
2//
3// https://github.com/martinmoene/variant-lite
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8#pragma once
9
10#ifndef NONSTD_VARIANT_LITE_HPP
11#define NONSTD_VARIANT_LITE_HPP
12
13#define variant_lite_MAJOR 1
14#define variant_lite_MINOR 1
15#define variant_lite_PATCH 0
16
17#define variant_lite_VERSION variant_STRINGIFY(variant_lite_MAJOR) "." variant_STRINGIFY(variant_lite_MINOR) "." variant_STRINGIFY(variant_lite_PATCH)
18
19#define variant_STRINGIFY( x ) variant_STRINGIFY_( x )
20#define variant_STRINGIFY_( x ) #x
21
22// variant-lite configuration:
23
24#define variant_VARIANT_DEFAULT 0
25#define variant_VARIANT_NONSTD 1
26#define variant_VARIANT_STD 2
27
28#if !defined( variant_CONFIG_SELECT_VARIANT )
29# define variant_CONFIG_SELECT_VARIANT ( variant_HAVE_STD_VARIANT ? variant_VARIANT_STD : variant_VARIANT_NONSTD )
30#endif
31
32#ifndef variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO
33# define variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO 0
34#endif
35
36#ifndef variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO
37# define variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO 0
38#endif
39
40// C++ language version detection (C++20 is speculative):
41// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
42
43#ifndef variant_CPLUSPLUS
44# if defined(_MSVC_LANG ) && !defined(__clang__)
45# define variant_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
46# else
47# define variant_CPLUSPLUS __cplusplus
48# endif
49#endif
50
51#define variant_CPP98_OR_GREATER ( variant_CPLUSPLUS >= 199711L )
52#define variant_CPP11_OR_GREATER ( variant_CPLUSPLUS >= 201103L )
53#define variant_CPP11_OR_GREATER_ ( variant_CPLUSPLUS >= 201103L )
54#define variant_CPP14_OR_GREATER ( variant_CPLUSPLUS >= 201402L )
55#define variant_CPP17_OR_GREATER ( variant_CPLUSPLUS >= 201703L )
56#define variant_CPP20_OR_GREATER ( variant_CPLUSPLUS >= 202000L )
57
58// Use C++17 std::variant if available and requested:
59
60#if variant_CPP17_OR_GREATER && defined(__has_include )
61# if __has_include( <variant> )
62# define variant_HAVE_STD_VARIANT 1
63# else
64# define variant_HAVE_STD_VARIANT 0
65# endif
66#else
67# define variant_HAVE_STD_VARIANT 0
68#endif
69
70#define variant_USES_STD_VARIANT ( (variant_CONFIG_SELECT_VARIANT == variant_VARIANT_STD) || ((variant_CONFIG_SELECT_VARIANT == variant_VARIANT_DEFAULT) && variant_HAVE_STD_VARIANT) )
71
72//
73// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
74//
75
76#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
77#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
78
79// C++17 std::in_place in <utility>:
80
81#if variant_CPP17_OR_GREATER
82
83#include <utility>
84
85namespace nonstd {
86
87using std::in_place;
88using std::in_place_type;
89using std::in_place_index;
90using std::in_place_t;
91using std::in_place_type_t;
92using std::in_place_index_t;
93
94#define nonstd_lite_in_place_t( T) std::in_place_t
95#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
96#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
97
98#define nonstd_lite_in_place( T) std::in_place_t{}
99#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
100#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
101
102} // namespace nonstd
103
104#else // variant_CPP17_OR_GREATER
105
106#include <cstddef>
107
108namespace nonstd {
109namespace detail {
110
111template< class T >
112struct in_place_type_tag {};
113
114template< std::size_t K >
115struct in_place_index_tag {};
116
117} // namespace detail
118
119struct in_place_t {};
120
121template< class T >
122inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
123{
124 return in_place_t();
125}
126
127template< std::size_t K >
128inline in_place_t in_place( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
129{
130 return in_place_t();
131}
132
133template< class T >
134inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
135{
136 return in_place_t();
137}
138
139template< std::size_t K >
140inline in_place_t in_place_index( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
141{
142 return in_place_t();
143}
144
145// mimic templated typedef:
146
147#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
148#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
149#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
150
151#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
152#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
153#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
154
155} // namespace nonstd
156
157#endif // variant_CPP17_OR_GREATER
158#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
159
160//
161// Use C++17 std::variant:
162//
163
164#if variant_USES_STD_VARIANT
165
166#include <functional> // std::hash<>
167#include <variant>
168
169#if ! variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO
170# define variant_size_V(T) nonstd::variant_size<T>::value
171#endif
172
173#if ! variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO
174# define variant_alternative_T(K,T) typename nonstd::variant_alternative<K,T >::type
175#endif
176
177namespace nonstd {
178
179 using std::variant;
180 using std::monostate;
181 using std::bad_variant_access;
182 using std::variant_size;
183 using std::variant_size_v;
184 using std::variant_alternative;
185 using std::variant_alternative_t;
186 using std::hash;
187
188 using std::visit;
189 using std::holds_alternative;
190 using std::get;
191 using std::get_if;
192 using std::operator==;
193 using std::operator!=;
194 using std::operator<;
195 using std::operator<=;
196 using std::operator>;
197 using std::operator>=;
198 using std::swap;
199
200 constexpr auto variant_npos = std::variant_npos;
201}
202
203#else // variant_USES_STD_VARIANT
204
205#include <cstddef>
206#include <limits>
207#include <new>
208#include <stdexcept>
209#include <utility>
210
211// variant-lite alignment configuration:
212
213#ifndef variant_CONFIG_MAX_ALIGN_HACK
214# define variant_CONFIG_MAX_ALIGN_HACK 0
215#endif
216
217#ifndef variant_CONFIG_ALIGN_AS
218// no default, used in #if defined()
219#endif
220
221#ifndef variant_CONFIG_ALIGN_AS_FALLBACK
222# define variant_CONFIG_ALIGN_AS_FALLBACK double
223#endif
224
225// half-open range [lo..hi):
226#define variant_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
227
228// Compiler versions:
229//
230// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
231// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
232// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
233// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
234// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
235// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
236// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
237// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
238// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
239// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
240
241#if defined(_MSC_VER ) && !defined(__clang__)
242# define variant_COMPILER_MSVC_VER (_MSC_VER )
243# define variant_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
244#else
245# define variant_COMPILER_MSVC_VER 0
246# define variant_COMPILER_MSVC_VERSION 0
247#endif
248
249#define variant_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
250
251#if defined(__clang__)
252# define variant_COMPILER_CLANG_VERSION variant_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
253#else
254# define variant_COMPILER_CLANG_VERSION 0
255#endif
256
257#if defined(__GNUC__) && !defined(__clang__)
258# define variant_COMPILER_GNUC_VERSION variant_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
259#else
260# define variant_COMPILER_GNUC_VERSION 0
261#endif
262
263#if variant_BETWEEN( variant_COMPILER_MSVC_VER, 1300, 1900 )
264# pragma warning( push )
265# pragma warning( disable: 4345 ) // initialization behavior changed
266#endif
267
268// Presence of language and library features:
269
270#define variant_HAVE( feature ) ( variant_HAVE_##feature )
271
272#ifdef _HAS_CPP0X
273# define variant_HAS_CPP0X _HAS_CPP0X
274#else
275# define variant_HAS_CPP0X 0
276#endif
277
278// Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
279
280#if variant_COMPILER_MSVC_VER >= 1900
281# undef variant_CPP11_OR_GREATER
282# define variant_CPP11_OR_GREATER 1
283#endif
284
285#define variant_CPP11_90 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1500)
286#define variant_CPP11_100 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1600)
287#define variant_CPP11_110 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1700)
288#define variant_CPP11_120 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1800)
289#define variant_CPP11_140 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1900)
290#define variant_CPP11_141 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1910)
291
292#define variant_CPP14_000 (variant_CPP14_OR_GREATER)
293#define variant_CPP17_000 (variant_CPP17_OR_GREATER)
294
295// Presence of C++11 language features:
296
297#define variant_HAVE_CONSTEXPR_11 variant_CPP11_140
298#define variant_HAVE_INITIALIZER_LIST variant_CPP11_120
299#define variant_HAVE_NOEXCEPT variant_CPP11_140
300#define variant_HAVE_NULLPTR variant_CPP11_100
301#define variant_HAVE_OVERRIDE variant_CPP11_140
302
303// Presence of C++14 language features:
304
305#define variant_HAVE_CONSTEXPR_14 variant_CPP14_000
306
307// Presence of C++17 language features:
308
309// no flag
310
311// Presence of C++ library features:
312
313#define variant_HAVE_TR1_TYPE_TRAITS (!! variant_COMPILER_GNUC_VERSION )
314#define variant_HAVE_TR1_ADD_POINTER (!! variant_COMPILER_GNUC_VERSION )
315
316#define variant_HAVE_CONDITIONAL variant_CPP11_120
317#define variant_HAVE_REMOVE_CV variant_CPP11_120
318#define variant_HAVE_STD_ADD_POINTER variant_CPP11_90
319#define variant_HAVE_TYPE_TRAITS variant_CPP11_90
320
321// C++ feature usage:
322
323#if variant_HAVE_CONSTEXPR_11
324# define variant_constexpr constexpr
325#else
326# define variant_constexpr /*constexpr*/
327#endif
328
329#if variant_HAVE_CONSTEXPR_14
330# define variant_constexpr14 constexpr
331#else
332# define variant_constexpr14 /*constexpr*/
333#endif
334
335#if variant_HAVE_NOEXCEPT
336# define variant_noexcept noexcept
337#else
338# define variant_noexcept /*noexcept*/
339#endif
340
341#if variant_HAVE_NULLPTR
342# define variant_nullptr nullptr
343#else
344# define variant_nullptr NULL
345#endif
346
347#if variant_HAVE_OVERRIDE
348# define variant_override override
349#else
350# define variant_override /*override*/
351#endif
352
353// additional includes:
354
355#if variant_CPP11_OR_GREATER
356# include <functional> // std::hash
357#endif
358
359#if variant_HAVE_INITIALIZER_LIST
360# include <initializer_list>
361#endif
362
363#if variant_HAVE_TYPE_TRAITS
364# include <type_traits>
365#elif variant_HAVE_TR1_TYPE_TRAITS
366# include <tr1/type_traits>
367#endif
368
369// Method enabling
370
371#if variant_CPP11_OR_GREATER
372
373# define variant_REQUIRES_T(...) \
374 , typename = typename std::enable_if<__VA_ARGS__>::type
375
376# define variant_REQUIRES_R(R, ...) \
377 typename std::enable_if<__VA_ARGS__, R>::type
378
379# define variant_REQUIRES_A(...) \
380 , typename std::enable_if<__VA_ARGS__, void*>::type = variant_nullptr
381
382#endif
383
384//
385// variant:
386//
387
388namespace nonstd { namespace variants {
389
390namespace detail {
391
392// C++11 emulation:
393
394#if variant_HAVE_STD_ADD_POINTER
395
396using std::add_pointer;
397
398#elif variant_HAVE_TR1_ADD_POINTER
399
400using std::tr1::add_pointer;
401
402#else
403
404template< class T > struct remove_reference { typedef T type; };
405template< class T > struct remove_reference<T&> { typedef T type; };
406
407template< class T > struct add_pointer
408{
409 typedef typename remove_reference<T>::type * type;
410};
411
412#endif // variant_HAVE_STD_ADD_POINTER
413
414#if variant_HAVE_REMOVE_CV
415
416using std::remove_cv;
417
418#else
419
420template< class T > struct remove_const { typedef T type; };
421template< class T > struct remove_const<const T> { typedef T type; };
422
423template< class T > struct remove_volatile { typedef T type; };
424template< class T > struct remove_volatile<volatile T> { typedef T type; };
425
426template< class T >
427struct remove_cv
428{
429 typedef typename remove_volatile<typename remove_const<T>::type>::type type;
430};
431
432#endif // variant_HAVE_REMOVE_CV
433
434#if variant_HAVE_CONDITIONAL
435
436using std::conditional;
437
438#else
439
440template< bool Cond, class Then, class Else >
441struct conditional;
442
443template< class Then, class Else >
444struct conditional< true , Then, Else > { typedef Then type; };
445
446template< class Then, class Else >
447struct conditional< false, Then, Else > { typedef Else type; };
448
449#endif // variant_HAVE_CONDITIONAL
450
451// typelist:
452
453#define variant_TL1( T1 ) detail::typelist< T1, detail::nulltype >
454#define variant_TL2( T1, T2) detail::typelist< T1, variant_TL1( T2) >
455#define variant_TL3( T1, T2, T3) detail::typelist< T1, variant_TL2( T2, T3) >
456#define variant_TL4( T1, T2, T3, T4) detail::typelist< T1, variant_TL3( T2, T3, T4) >
457#define variant_TL5( T1, T2, T3, T4, T5) detail::typelist< T1, variant_TL4( T2, T3, T4, T5) >
458#define variant_TL6( T1, T2, T3, T4, T5, T6) detail::typelist< T1, variant_TL5( T2, T3, T4, T5, T6) >
459#define variant_TL7( T1, T2, T3, T4, T5, T6, T7) detail::typelist< T1, variant_TL6( T2, T3, T4, T5, T6, T7) >
460#define variant_TL8( T1, T2, T3, T4, T5, T6, T7, T8) detail::typelist< T1, variant_TL7( T2, T3, T4, T5, T6, T7, T8) >
461#define variant_TL9( T1, T2, T3, T4, T5, T6, T7, T8, T9) detail::typelist< T1, variant_TL8( T2, T3, T4, T5, T6, T7, T8, T9) >
462#define variant_TL10( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) detail::typelist< T1, variant_TL9( T2, T3, T4, T5, T6, T7, T8, T9, T10) >
463#define variant_TL11( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) detail::typelist< T1, variant_TL10( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) >
464#define variant_TL12( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) detail::typelist< T1, variant_TL11( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) >
465#define variant_TL13( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) detail::typelist< T1, variant_TL12( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) >
466#define variant_TL14( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) detail::typelist< T1, variant_TL13( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) >
467#define variant_TL15( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) detail::typelist< T1, variant_TL14( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) >
468#define variant_TL16( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) detail::typelist< T1, variant_TL15( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) >
469
470
471// variant parameter unused type tags:
472
473template< class T >
474struct TX : T
475{
476 inline TX<T> operator+ ( ) const { return TX<T>(); }
477 inline TX<T> operator- ( ) const { return TX<T>(); }
478
479 inline TX<T> operator! ( ) const { return TX<T>(); }
480 inline TX<T> operator~ ( ) const { return TX<T>(); }
481
482 inline TX<T>*operator& ( ) const { return variant_nullptr; }
483
484 template< class U > inline TX<T> operator* ( U const & ) const { return TX<T>(); }
485 template< class U > inline TX<T> operator/ ( U const & ) const { return TX<T>(); }
486
487 template< class U > inline TX<T> operator% ( U const & ) const { return TX<T>(); }
488 template< class U > inline TX<T> operator+ ( U const & ) const { return TX<T>(); }
489 template< class U > inline TX<T> operator- ( U const & ) const { return TX<T>(); }
490
491 template< class U > inline TX<T> operator<<( U const & ) const { return TX<T>(); }
492 template< class U > inline TX<T> operator>>( U const & ) const { return TX<T>(); }
493
494 inline bool operator==( T const & ) const { return false; }
495 inline bool operator< ( T const & ) const { return false; }
496
497 template< class U > inline TX<T> operator& ( U const & ) const { return TX<T>(); }
498 template< class U > inline TX<T> operator| ( U const & ) const { return TX<T>(); }
499 template< class U > inline TX<T> operator^ ( U const & ) const { return TX<T>(); }
500
501 template< class U > inline TX<T> operator&&( U const & ) const { return TX<T>(); }
502 template< class U > inline TX<T> operator||( U const & ) const { return TX<T>(); }
503};
504
505struct S0{}; typedef TX<S0> T0;
506struct S1{}; typedef TX<S1> T1;
507struct S2{}; typedef TX<S2> T2;
508struct S3{}; typedef TX<S3> T3;
509struct S4{}; typedef TX<S4> T4;
510struct S5{}; typedef TX<S5> T5;
511struct S6{}; typedef TX<S6> T6;
512struct S7{}; typedef TX<S7> T7;
513struct S8{}; typedef TX<S8> T8;
514struct S9{}; typedef TX<S9> T9;
515struct S10{}; typedef TX<S10> T10;
516struct S11{}; typedef TX<S11> T11;
517struct S12{}; typedef TX<S12> T12;
518struct S13{}; typedef TX<S13> T13;
519struct S14{}; typedef TX<S14> T14;
520struct S15{}; typedef TX<S15> T15;
521
522
523struct nulltype{};
524
525template< class Head, class Tail >
526struct typelist
527{
528 typedef Head head;
529 typedef Tail tail;
530};
531
532// typelist max element size:
533
534template< class List >
535struct typelist_max;
536
537template<>
538struct typelist_max< nulltype >
539{
540 enum V { value = 0 } ;
541 typedef void type;
542};
543
544template< class Head, class Tail >
545struct typelist_max< typelist<Head, Tail> >
546{
547private:
548 enum TV { tail_value = size_t( typelist_max<Tail>::value ) };
549
550 typedef typename typelist_max<Tail>::type tail_type;
551
552public:
553 enum V { value = (sizeof( Head ) > tail_value) ? sizeof( Head ) : std::size_t( tail_value ) } ;
554
555 typedef typename conditional< (sizeof( Head ) > tail_value), Head, tail_type>::type type;
556};
557
558#if variant_CPP11_OR_GREATER
559
560// typelist max alignof element type:
561
562template< class List >
563struct typelist_max_alignof;
564
565template<>
566struct typelist_max_alignof< nulltype >
567{
568 enum V { value = 0 } ;
569};
570
571template< class Head, class Tail >
572struct typelist_max_alignof< typelist<Head, Tail> >
573{
574private:
575 enum TV { tail_value = size_t( typelist_max_alignof<Tail>::value ) };
576
577public:
578 enum V { value = (alignof( Head ) > tail_value) ? alignof( Head ) : std::size_t( tail_value ) };
579};
580
581#endif
582
583// typelist size (length):
584
585template< class List >
586struct typelist_size
587{
588 enum V { value = 1 };
589};
590
591template<> struct typelist_size< T0 > { enum V { value = 0 }; };
592template<> struct typelist_size< T1 > { enum V { value = 0 }; };
593template<> struct typelist_size< T2 > { enum V { value = 0 }; };
594template<> struct typelist_size< T3 > { enum V { value = 0 }; };
595template<> struct typelist_size< T4 > { enum V { value = 0 }; };
596template<> struct typelist_size< T5 > { enum V { value = 0 }; };
597template<> struct typelist_size< T6 > { enum V { value = 0 }; };
598template<> struct typelist_size< T7 > { enum V { value = 0 }; };
599template<> struct typelist_size< T8 > { enum V { value = 0 }; };
600template<> struct typelist_size< T9 > { enum V { value = 0 }; };
601template<> struct typelist_size< T10 > { enum V { value = 0 }; };
602template<> struct typelist_size< T11 > { enum V { value = 0 }; };
603template<> struct typelist_size< T12 > { enum V { value = 0 }; };
604template<> struct typelist_size< T13 > { enum V { value = 0 }; };
605template<> struct typelist_size< T14 > { enum V { value = 0 }; };
606template<> struct typelist_size< T15 > { enum V { value = 0 }; };
607
608
609template<> struct typelist_size< nulltype > { enum V { value = 0 } ; };
610
611template< class Head, class Tail >
612struct typelist_size< typelist<Head, Tail> >
613{
614 enum V { value = typelist_size<Head>::value + typelist_size<Tail>::value };
615};
616
617// typelist index of type:
618
619template< class List, class T >
620struct typelist_index_of;
621
622template< class T >
623struct typelist_index_of< nulltype, T >
624{
625 enum V { value = -1 };
626};
627
628template< class Tail, class T >
629struct typelist_index_of< typelist<T, Tail>, T >
630{
631 enum V { value = 0 };
632};
633
634template< class Head, class Tail, class T >
635struct typelist_index_of< typelist<Head, Tail>, T >
636{
637private:
638 enum TV { nextVal = typelist_index_of<Tail, T>::value };
639
640public:
641 enum V { value = nextVal == -1 ? -1 : 1 + nextVal } ;
642};
643
644// typelist type at index:
645
646template< class List, std::size_t i>
647struct typelist_type_at;
648
649template< class Head, class Tail >
650struct typelist_type_at< typelist<Head, Tail>, 0 >
651{
652 typedef Head type;
653};
654
655template< class Head, class Tail, std::size_t i >
656struct typelist_type_at< typelist<Head, Tail>, i >
657{
658 typedef typename typelist_type_at<Tail, i - 1>::type type;
659};
660
661#if variant_CONFIG_MAX_ALIGN_HACK
662
663// Max align, use most restricted type for alignment:
664
665#define variant_UNIQUE( name ) variant_UNIQUE2( name, __LINE__ )
666#define variant_UNIQUE2( name, line ) variant_UNIQUE3( name, line )
667#define variant_UNIQUE3( name, line ) name ## line
668
669#define variant_ALIGN_TYPE( type ) \
670 type variant_UNIQUE( _t ); struct_t< type > variant_UNIQUE( _st )
671
672template< class T >
673struct struct_t { T _; };
674
675union max_align_t
676{
677 variant_ALIGN_TYPE( char );
678 variant_ALIGN_TYPE( short int );
679 variant_ALIGN_TYPE( int );
680 variant_ALIGN_TYPE( long int );
681 variant_ALIGN_TYPE( float );
682 variant_ALIGN_TYPE( double );
683 variant_ALIGN_TYPE( long double );
684 variant_ALIGN_TYPE( char * );
685 variant_ALIGN_TYPE( short int * );
686 variant_ALIGN_TYPE( int * );
687 variant_ALIGN_TYPE( long int * );
688 variant_ALIGN_TYPE( float * );
689 variant_ALIGN_TYPE( double * );
690 variant_ALIGN_TYPE( long double * );
691 variant_ALIGN_TYPE( void * );
692
693#ifdef HAVE_LONG_LONG
694 variant_ALIGN_TYPE( long long );
695#endif
696
697 struct Unknown;
698
699 Unknown ( * variant_UNIQUE(_) )( Unknown );
700 Unknown * Unknown::* variant_UNIQUE(_);
701 Unknown ( Unknown::* variant_UNIQUE(_) )( Unknown );
702
703 struct_t< Unknown ( * )( Unknown) > variant_UNIQUE(_);
704 struct_t< Unknown * Unknown::* > variant_UNIQUE(_);
705 struct_t< Unknown ( Unknown::* )(Unknown) > variant_UNIQUE(_);
706};
707
708#undef variant_UNIQUE
709#undef variant_UNIQUE2
710#undef variant_UNIQUE3
711
712#undef variant_ALIGN_TYPE
713
714#elif defined( variant_CONFIG_ALIGN_AS ) // variant_CONFIG_MAX_ALIGN_HACK
715
716// Use user-specified type for alignment:
717
718#define variant_ALIGN_AS( unused ) \
719 variant_CONFIG_ALIGN_AS
720
721#else // variant_CONFIG_MAX_ALIGN_HACK
722
723// Determine POD type to use for alignment:
724
725#define variant_ALIGN_AS( to_align ) \
726 typename detail::type_of_size< detail::alignment_types, detail::alignment_of< to_align >::value >::type
727
728template< typename T >
729struct alignment_of;
730
731template< typename T >
732struct alignment_of_hack
733{
734 char c;
735 T t;
736 alignment_of_hack();
737};
738
739template< size_t A, size_t S >
740struct alignment_logic
741{
742 enum V { value = A < S ? A : S };
743};
744
745template< typename T >
746struct alignment_of
747{
748 enum V { value = alignment_logic<
749 sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value, };
750};
751
752template< typename List, size_t N >
753struct type_of_size
754{
755 typedef typename conditional<
756 N == sizeof( typename List::head ),
757 typename List::head,
758 typename type_of_size<typename List::tail, N >::type >::type type;
759};
760
761template< size_t N >
762struct type_of_size< nulltype, N >
763{
764 typedef variant_CONFIG_ALIGN_AS_FALLBACK type;
765};
766
767template< typename T>
768struct struct_t { T _; };
769
770#define variant_ALIGN_TYPE( type ) \
771 typelist< type , typelist< struct_t< type >
772
773struct Unknown;
774
775typedef
776 variant_ALIGN_TYPE( char ),
777 variant_ALIGN_TYPE( short ),
778 variant_ALIGN_TYPE( int ),
779 variant_ALIGN_TYPE( long ),
780 variant_ALIGN_TYPE( float ),
781 variant_ALIGN_TYPE( double ),
782 variant_ALIGN_TYPE( long double ),
783
784 variant_ALIGN_TYPE( char *),
785 variant_ALIGN_TYPE( short * ),
786 variant_ALIGN_TYPE( int * ),
787 variant_ALIGN_TYPE( long * ),
788 variant_ALIGN_TYPE( float * ),
789 variant_ALIGN_TYPE( double * ),
790 variant_ALIGN_TYPE( long double * ),
791
792 variant_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
793 variant_ALIGN_TYPE( Unknown * Unknown::* ),
794 variant_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
795
796 nulltype
797 > > > > > > > > > > > > > >
798 > > > > > > > > > > > > > >
799 > > > > > >
800 alignment_types;
801
802#undef variant_ALIGN_TYPE
803
804#endif // variant_CONFIG_MAX_ALIGN_HACK
805
806template< typename T>
807inline std::size_t hash( T const & v )
808{
809 // primes:
810 unsigned const int a = 54059;
811 unsigned const int b = 76963;
812 unsigned const int h0 = 37;
813
814 unsigned int h = h0;
815 unsigned char const * s = reinterpret_cast<unsigned char const *>( &v );
816
817 for ( std::size_t i = 0; i < sizeof(v); ++i, ++s )
818 {
819 h = (h * a) ^ (*s * b);
820 }
821 return h;
822}
823
824
825
826
827
828template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
829struct helper
830{
831 typedef signed char type_index_t;
832 typedef variant_TL16( T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 ) variant_types;
833
834 template< class U >
835 static U * as( void * data )
836 {
837 return reinterpret_cast<U*>( data );
838 }
839
840 template< class U >
841 static U const * as( void const * data )
842 {
843 return reinterpret_cast<const U*>( data );
844 }
845
846 static type_index_t to_index_t( std::size_t index )
847 {
848 return static_cast<type_index_t>( index );
849 }
850
851 static void destroy( type_index_t index, void * data )
852 {
853 switch ( index )
854 {
855 case 0: as<T0>( data )->~T0(); break;
856 case 1: as<T1>( data )->~T1(); break;
857 case 2: as<T2>( data )->~T2(); break;
858 case 3: as<T3>( data )->~T3(); break;
859 case 4: as<T4>( data )->~T4(); break;
860 case 5: as<T5>( data )->~T5(); break;
861 case 6: as<T6>( data )->~T6(); break;
862 case 7: as<T7>( data )->~T7(); break;
863 case 8: as<T8>( data )->~T8(); break;
864 case 9: as<T9>( data )->~T9(); break;
865 case 10: as<T10>( data )->~T10(); break;
866 case 11: as<T11>( data )->~T11(); break;
867 case 12: as<T12>( data )->~T12(); break;
868 case 13: as<T13>( data )->~T13(); break;
869 case 14: as<T14>( data )->~T14(); break;
870 case 15: as<T15>( data )->~T15(); break;
871
872 }
873 }
874
875#if variant_CPP11_OR_GREATER
876 template< class T, class... Args >
877 static type_index_t construct_t( void * data, Args&&... args )
878 {
879 new( data ) T( std::forward<Args>(args)... );
880
881 return to_index_t( detail::typelist_index_of< variant_types, T>::value );
882 }
883
884 template< std::size_t K, class... Args >
885 static type_index_t construct_i( void * data, Args&&... args )
886 {
887 using type = typename detail::typelist_type_at< variant_types, K >::type;
888
889 construct_t< type >( data, std::forward<Args>(args)... );
890
891 return to_index_t( K );
892 }
893
894 static type_index_t move( type_index_t const from_index, void * from_value, void * to_value )
895 {
896 switch ( from_index )
897 {
898 case 0: new( to_value ) T0( std::forward<T0>( *as<T0>( from_value ) ) ); break;
899 case 1: new( to_value ) T1( std::forward<T1>( *as<T1>( from_value ) ) ); break;
900 case 2: new( to_value ) T2( std::forward<T2>( *as<T2>( from_value ) ) ); break;
901 case 3: new( to_value ) T3( std::forward<T3>( *as<T3>( from_value ) ) ); break;
902 case 4: new( to_value ) T4( std::forward<T4>( *as<T4>( from_value ) ) ); break;
903 case 5: new( to_value ) T5( std::forward<T5>( *as<T5>( from_value ) ) ); break;
904 case 6: new( to_value ) T6( std::forward<T6>( *as<T6>( from_value ) ) ); break;
905 case 7: new( to_value ) T7( std::forward<T7>( *as<T7>( from_value ) ) ); break;
906 case 8: new( to_value ) T8( std::forward<T8>( *as<T8>( from_value ) ) ); break;
907 case 9: new( to_value ) T9( std::forward<T9>( *as<T9>( from_value ) ) ); break;
908 case 10: new( to_value ) T10( std::forward<T10>( *as<T10>( from_value ) ) ); break;
909 case 11: new( to_value ) T11( std::forward<T11>( *as<T11>( from_value ) ) ); break;
910 case 12: new( to_value ) T12( std::forward<T12>( *as<T12>( from_value ) ) ); break;
911 case 13: new( to_value ) T13( std::forward<T13>( *as<T13>( from_value ) ) ); break;
912 case 14: new( to_value ) T14( std::forward<T14>( *as<T14>( from_value ) ) ); break;
913 case 15: new( to_value ) T15( std::forward<T15>( *as<T15>( from_value ) ) ); break;
914
915 }
916 return from_index;
917 }
918#endif
919
920 static type_index_t copy( type_index_t const from_index, const void * from_value, void * to_value )
921 {
922 switch ( from_index )
923 {
924 case 0: new( to_value ) T0( *as<T0>( from_value ) ); break;
925 case 1: new( to_value ) T1( *as<T1>( from_value ) ); break;
926 case 2: new( to_value ) T2( *as<T2>( from_value ) ); break;
927 case 3: new( to_value ) T3( *as<T3>( from_value ) ); break;
928 case 4: new( to_value ) T4( *as<T4>( from_value ) ); break;
929 case 5: new( to_value ) T5( *as<T5>( from_value ) ); break;
930 case 6: new( to_value ) T6( *as<T6>( from_value ) ); break;
931 case 7: new( to_value ) T7( *as<T7>( from_value ) ); break;
932 case 8: new( to_value ) T8( *as<T8>( from_value ) ); break;
933 case 9: new( to_value ) T9( *as<T9>( from_value ) ); break;
934 case 10: new( to_value ) T10( *as<T10>( from_value ) ); break;
935 case 11: new( to_value ) T11( *as<T11>( from_value ) ); break;
936 case 12: new( to_value ) T12( *as<T12>( from_value ) ); break;
937 case 13: new( to_value ) T13( *as<T13>( from_value ) ); break;
938 case 14: new( to_value ) T14( *as<T14>( from_value ) ); break;
939 case 15: new( to_value ) T15( *as<T15>( from_value ) ); break;
940
941 }
942 return from_index;
943 }
944};
945
946} // namespace detail
947
948//
949// Variant:
950//
951
952template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
953class variant;
954
955class monostate{};
956
957inline variant_constexpr bool operator< ( monostate, monostate ) variant_noexcept { return false; }
958inline variant_constexpr bool operator> ( monostate, monostate ) variant_noexcept { return false; }
959inline variant_constexpr bool operator<=( monostate, monostate ) variant_noexcept { return true; }
960inline variant_constexpr bool operator>=( monostate, monostate ) variant_noexcept { return true; }
961inline variant_constexpr bool operator==( monostate, monostate ) variant_noexcept { return true; }
962inline variant_constexpr bool operator!=( monostate, monostate ) variant_noexcept { return false; }
963
964// obtain the size of the variant's list of alternatives at compile time
965
966template< class T >
967struct variant_size; /* undefined */
968
969template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
970struct variant_size< variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
971{
972 enum _ { value = detail::typelist_size< variant_TL16(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) >::value };
973};
974
975#if variant_CPP14_OR_GREATER
976template< class T >
977constexpr std::size_t variant_size_v = variant_size<T>::value;
978#endif
979
980#if ! variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO
981# define variant_size_V(T) nonstd::variant_size<T>::value
982#endif
983
984// obtain the type of the alternative specified by its index, at compile time:
985
986template< std::size_t K, class T >
987struct variant_alternative; /* undefined */
988
989template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
990struct variant_alternative< K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
991{
992 typedef typename detail::typelist_type_at<variant_TL16(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), K>::type type;
993};
994
995#if variant_CPP11_OR_GREATER
996template< std::size_t K, class T >
997using variant_alternative_t = typename variant_alternative<K, T>::type;
998#endif
999
1000#if ! variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO
1001# define variant_alternative_T(K,T) typename nonstd::variant_alternative<K,T >::type
1002#endif
1003
1004// NTS:implement specializes the std::uses_allocator type trait
1005// std::uses_allocator<nonstd::variant>
1006
1007// index of the variant in the invalid state (constant)
1008
1009#if variant_CPP11_OR_GREATER
1010variant_constexpr std::size_t variant_npos = static_cast<std::size_t>( -1 );
1011#else
1012static const std::size_t variant_npos = static_cast<std::size_t>( -1 );
1013#endif
1014
1015class bad_variant_access : public std::exception
1016{
1017public:
1018#if variant_CPP11_OR_GREATER
1019 virtual const char* what() const variant_noexcept variant_override
1020#else
1021 virtual const char* what() const throw()
1022#endif
1023 {
1024 return "bad variant access";
1025 }
1026};
1027
1028template<
1029 class T0,
1030 class T1 = detail::T1,
1031 class T2 = detail::T2,
1032 class T3 = detail::T3,
1033 class T4 = detail::T4,
1034 class T5 = detail::T5,
1035 class T6 = detail::T6,
1036 class T7 = detail::T7,
1037 class T8 = detail::T8,
1038 class T9 = detail::T9,
1039 class T10 = detail::T10,
1040 class T11 = detail::T11,
1041 class T12 = detail::T12,
1042 class T13 = detail::T13,
1043 class T14 = detail::T14,
1044 class T15 = detail::T15
1045 >
1046class variant
1047{
1048 typedef detail::helper< T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 > helper_type;
1049 typedef variant_TL16( T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 ) variant_types;
1050
1051public:
1052 variant() : type_index( 0 ) { new( ptr() ) T0(); }
1053
1054 variant( T0 const & t0 ) : type_index( 0 ) { new( ptr() ) T0( t0 ); }
1055 variant( T1 const & t1 ) : type_index( 1 ) { new( ptr() ) T1( t1 ); }
1056 variant( T2 const & t2 ) : type_index( 2 ) { new( ptr() ) T2( t2 ); }
1057 variant( T3 const & t3 ) : type_index( 3 ) { new( ptr() ) T3( t3 ); }
1058 variant( T4 const & t4 ) : type_index( 4 ) { new( ptr() ) T4( t4 ); }
1059 variant( T5 const & t5 ) : type_index( 5 ) { new( ptr() ) T5( t5 ); }
1060 variant( T6 const & t6 ) : type_index( 6 ) { new( ptr() ) T6( t6 ); }
1061 variant( T7 const & t7 ) : type_index( 7 ) { new( ptr() ) T7( t7 ); }
1062 variant( T8 const & t8 ) : type_index( 8 ) { new( ptr() ) T8( t8 ); }
1063 variant( T9 const & t9 ) : type_index( 9 ) { new( ptr() ) T9( t9 ); }
1064 variant( T10 const & t10 ) : type_index( 10 ) { new( ptr() ) T10( t10 ); }
1065 variant( T11 const & t11 ) : type_index( 11 ) { new( ptr() ) T11( t11 ); }
1066 variant( T12 const & t12 ) : type_index( 12 ) { new( ptr() ) T12( t12 ); }
1067 variant( T13 const & t13 ) : type_index( 13 ) { new( ptr() ) T13( t13 ); }
1068 variant( T14 const & t14 ) : type_index( 14 ) { new( ptr() ) T14( t14 ); }
1069 variant( T15 const & t15 ) : type_index( 15 ) { new( ptr() ) T15( t15 ); }
1070
1071
1072#if variant_CPP11_OR_GREATER
1073 variant( T0 && t0 ) : type_index( 0 ) { new( ptr() ) T0( std::move(t0) ); }
1074 variant( T1 && t1 ) : type_index( 1 ) { new( ptr() ) T1( std::move(t1) ); }
1075 variant( T2 && t2 ) : type_index( 2 ) { new( ptr() ) T2( std::move(t2) ); }
1076 variant( T3 && t3 ) : type_index( 3 ) { new( ptr() ) T3( std::move(t3) ); }
1077 variant( T4 && t4 ) : type_index( 4 ) { new( ptr() ) T4( std::move(t4) ); }
1078 variant( T5 && t5 ) : type_index( 5 ) { new( ptr() ) T5( std::move(t5) ); }
1079 variant( T6 && t6 ) : type_index( 6 ) { new( ptr() ) T6( std::move(t6) ); }
1080 variant( T7 && t7 ) : type_index( 7 ) { new( ptr() ) T7( std::move(t7) ); }
1081 variant( T8 && t8 ) : type_index( 8 ) { new( ptr() ) T8( std::move(t8) ); }
1082 variant( T9 && t9 ) : type_index( 9 ) { new( ptr() ) T9( std::move(t9) ); }
1083 variant( T10 && t10 ) : type_index( 10 ) { new( ptr() ) T10( std::move(t10) ); }
1084 variant( T11 && t11 ) : type_index( 11 ) { new( ptr() ) T11( std::move(t11) ); }
1085 variant( T12 && t12 ) : type_index( 12 ) { new( ptr() ) T12( std::move(t12) ); }
1086 variant( T13 && t13 ) : type_index( 13 ) { new( ptr() ) T13( std::move(t13) ); }
1087 variant( T14 && t14 ) : type_index( 14 ) { new( ptr() ) T14( std::move(t14) ); }
1088 variant( T15 && t15 ) : type_index( 15 ) { new( ptr() ) T15( std::move(t15) ); }
1089
1090#endif
1091
1092 variant(variant const & other)
1093 : type_index( other.type_index )
1094 {
1095 (void) helper_type::copy( other.type_index, other.ptr(), ptr() );
1096 }
1097
1098#if variant_CPP11_OR_GREATER
1099
1100 variant( variant && other ) noexcept(
1101 std::is_nothrow_move_constructible<T0>::value &&
1102 std::is_nothrow_move_constructible<T1>::value &&
1103 std::is_nothrow_move_constructible<T2>::value &&
1104 std::is_nothrow_move_constructible<T3>::value &&
1105 std::is_nothrow_move_constructible<T4>::value &&
1106 std::is_nothrow_move_constructible<T5>::value &&
1107 std::is_nothrow_move_constructible<T6>::value &&
1108 std::is_nothrow_move_constructible<T7>::value &&
1109 std::is_nothrow_move_constructible<T8>::value &&
1110 std::is_nothrow_move_constructible<T9>::value &&
1111 std::is_nothrow_move_constructible<T10>::value &&
1112 std::is_nothrow_move_constructible<T11>::value &&
1113 std::is_nothrow_move_constructible<T12>::value &&
1114 std::is_nothrow_move_constructible<T13>::value &&
1115 std::is_nothrow_move_constructible<T14>::value &&
1116 std::is_nothrow_move_constructible<T15>::value)
1117 : type_index( other.type_index )
1118 {
1119 (void) helper_type::move( other.type_index, other.ptr(), ptr() );
1120 }
1121
1122 template< std::size_t K >
1123 using type_at_t = typename detail::typelist_type_at< variant_types, K >::type;
1124
1125 template< class T, class... Args
1126 variant_REQUIRES_T( std::is_constructible< T, Args...>::value )
1127 >
1128 explicit variant( nonstd_lite_in_place_type_t(T), Args&&... args)
1129 {
1130 type_index = variant_npos_internal();
1131 type_index = helper_type::template construct_t<T>( ptr(), std::forward<Args>(args)... );
1132 }
1133
1134 template< class T, class U, class... Args
1135 variant_REQUIRES_T( std::is_constructible< T, std::initializer_list<U>&, Args...>::value )
1136 >
1137 explicit variant( nonstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
1138 {
1139 type_index = variant_npos_internal();
1140 type_index = helper_type::template construct_t<T>( ptr(), il, std::forward<Args>(args)... );
1141 }
1142
1143 template< std::size_t K, class... Args
1144 variant_REQUIRES_T( std::is_constructible< type_at_t<K>, Args...>::value )
1145 >
1146 explicit variant( nonstd_lite_in_place_index_t(K), Args&&... args )
1147 {
1148 type_index = variant_npos_internal();
1149 type_index = helper_type::template construct_i<K>( ptr(), std::forward<Args>(args)... );
1150 }
1151
1152 template< size_t K, class U, class... Args
1153 variant_REQUIRES_T( std::is_constructible< type_at_t<K>, std::initializer_list<U>&, Args...>::value )
1154 >
1155 explicit variant( nonstd_lite_in_place_index_t(K), std::initializer_list<U> il, Args&&... args )
1156 {
1157 type_index = variant_npos_internal();
1158 type_index = helper_type::template construct_i<K>( ptr(), il, std::forward<Args>(args)... );
1159 }
1160
1161#endif // variant_CPP11_OR_GREATER
1162
1163 ~variant()
1164 {
1165 helper_type::destroy( type_index, ptr() );
1166 }
1167
1168 variant & operator=( variant const & other )
1169 {
1170 return copy_assign( other );
1171 }
1172
1173#if variant_CPP11_OR_GREATER
1174
1175 variant & operator=( variant && other ) noexcept(
1176 std::is_nothrow_move_assignable<T0>::value &&
1177 std::is_nothrow_move_assignable<T1>::value &&
1178 std::is_nothrow_move_assignable<T2>::value &&
1179 std::is_nothrow_move_assignable<T3>::value &&
1180 std::is_nothrow_move_assignable<T4>::value &&
1181 std::is_nothrow_move_assignable<T5>::value &&
1182 std::is_nothrow_move_assignable<T6>::value &&
1183 std::is_nothrow_move_assignable<T7>::value &&
1184 std::is_nothrow_move_assignable<T8>::value &&
1185 std::is_nothrow_move_assignable<T9>::value &&
1186 std::is_nothrow_move_assignable<T10>::value &&
1187 std::is_nothrow_move_assignable<T11>::value &&
1188 std::is_nothrow_move_assignable<T12>::value &&
1189 std::is_nothrow_move_assignable<T13>::value &&
1190 std::is_nothrow_move_assignable<T14>::value &&
1191 std::is_nothrow_move_assignable<T15>::value)
1192 {
1193 return move_assign( std::forward<variant>( other ) );
1194 }
1195
1196 variant & operator=( T0 && t0 ) { return move_assign_value<T0,0>( std::forward<T0>( t0 ) ); }
1197 variant & operator=( T1 && t1 ) { return move_assign_value<T1,1>( std::forward<T1>( t1 ) ); }
1198 variant & operator=( T2 && t2 ) { return move_assign_value<T2,2>( std::forward<T2>( t2 ) ); }
1199 variant & operator=( T3 && t3 ) { return move_assign_value<T3,3>( std::forward<T3>( t3 ) ); }
1200 variant & operator=( T4 && t4 ) { return move_assign_value<T4,4>( std::forward<T4>( t4 ) ); }
1201 variant & operator=( T5 && t5 ) { return move_assign_value<T5,5>( std::forward<T5>( t5 ) ); }
1202 variant & operator=( T6 && t6 ) { return move_assign_value<T6,6>( std::forward<T6>( t6 ) ); }
1203 variant & operator=( T7 && t7 ) { return move_assign_value<T7,7>( std::forward<T7>( t7 ) ); }
1204 variant & operator=( T8 && t8 ) { return move_assign_value<T8,8>( std::forward<T8>( t8 ) ); }
1205 variant & operator=( T9 && t9 ) { return move_assign_value<T9,9>( std::forward<T9>( t9 ) ); }
1206 variant & operator=( T10 && t10 ) { return move_assign_value<T10,10>( std::forward<T10>( t10 ) ); }
1207 variant & operator=( T11 && t11 ) { return move_assign_value<T11,11>( std::forward<T11>( t11 ) ); }
1208 variant & operator=( T12 && t12 ) { return move_assign_value<T12,12>( std::forward<T12>( t12 ) ); }
1209 variant & operator=( T13 && t13 ) { return move_assign_value<T13,13>( std::forward<T13>( t13 ) ); }
1210 variant & operator=( T14 && t14 ) { return move_assign_value<T14,14>( std::forward<T14>( t14 ) ); }
1211 variant & operator=( T15 && t15 ) { return move_assign_value<T15,15>( std::forward<T15>( t15 ) ); }
1212
1213#else
1214 variant & operator=( T0 const & t0 ) { return copy_assign_value<T0,0>( t0 ); }
1215 variant & operator=( T1 const & t1 ) { return copy_assign_value<T1,1>( t1 ); }
1216 variant & operator=( T2 const & t2 ) { return copy_assign_value<T2,2>( t2 ); }
1217 variant & operator=( T3 const & t3 ) { return copy_assign_value<T3,3>( t3 ); }
1218 variant & operator=( T4 const & t4 ) { return copy_assign_value<T4,4>( t4 ); }
1219 variant & operator=( T5 const & t5 ) { return copy_assign_value<T5,5>( t5 ); }
1220 variant & operator=( T6 const & t6 ) { return copy_assign_value<T6,6>( t6 ); }
1221 variant & operator=( T7 const & t7 ) { return copy_assign_value<T7,7>( t7 ); }
1222 variant & operator=( T8 const & t8 ) { return copy_assign_value<T8,8>( t8 ); }
1223 variant & operator=( T9 const & t9 ) { return copy_assign_value<T9,9>( t9 ); }
1224 variant & operator=( T10 const & t10 ) { return copy_assign_value<T10,10>( t10 ); }
1225 variant & operator=( T11 const & t11 ) { return copy_assign_value<T11,11>( t11 ); }
1226 variant & operator=( T12 const & t12 ) { return copy_assign_value<T12,12>( t12 ); }
1227 variant & operator=( T13 const & t13 ) { return copy_assign_value<T13,13>( t13 ); }
1228 variant & operator=( T14 const & t14 ) { return copy_assign_value<T14,14>( t14 ); }
1229 variant & operator=( T15 const & t15 ) { return copy_assign_value<T15,15>( t15 ); }
1230
1231#endif
1232
1233 std::size_t index() const
1234 {
1235 return variant_npos_internal() == type_index ? variant_npos : static_cast<std::size_t>( type_index );
1236 }
1237
1238 bool valueless_by_exception() const
1239 {
1240 return type_index == variant_npos_internal();
1241 }
1242
1243#if variant_CPP11_OR_GREATER
1244 template< class T, class... Args
1245 variant_REQUIRES_T( std::is_constructible< T, Args...>::value )
1246 >
1247 T& emplace( Args&&... args )
1248 {
1249 helper_type::destroy( type_index, ptr() );
1250 type_index = variant_npos_internal();
1251 type_index = helper_type::template construct_t<T>( ptr(), std::forward<Args>(args)... );
1252
1253 return *as<T>();
1254 }
1255
1256 template< class T, class U, class... Args
1257 variant_REQUIRES_T( std::is_constructible< T, std::initializer_list<U>&, Args...>::value )
1258 >
1259 T& emplace( std::initializer_list<U> il, Args&&... args )
1260 {
1261 helper_type::destroy( type_index, ptr() );
1262 type_index = variant_npos_internal();
1263 type_index = helper_type::template construct_t<T>( ptr(), il, std::forward<Args>(args)... );
1264
1265 return *as<T>();
1266 }
1267
1268 template< size_t K, class... Args
1269 variant_REQUIRES_T( std::is_constructible< type_at_t<K>, Args...>::value )
1270 >
1271 variant_alternative_t<K, variant> & emplace( Args&&... args )
1272 {
1273 return this->template emplace< type_at_t<K> >( std::forward<Args>(args)... );
1274 }
1275
1276 template< size_t K, class U, class... Args
1277 variant_REQUIRES_T( std::is_constructible< type_at_t<K>, std::initializer_list<U>&, Args...>::value )
1278 >
1279 variant_alternative_t<K, variant> & emplace( std::initializer_list<U> il, Args&&... args )
1280 {
1281 return this->template emplace< type_at_t<K> >( il, std::forward<Args>(args)... );
1282 }
1283
1284#endif // variant_CPP11_OR_GREATER
1285
1286 void swap( variant & other ) variant_noexcept
1287 {
1288 if ( valueless_by_exception() && other.valueless_by_exception() )
1289 {
1290 // no effect
1291 }
1292 else if ( type_index == other.type_index )
1293 {
1294 this->swap_value( type_index, other );
1295 }
1296 else
1297 {
1298 variant tmp( *this );
1299 *this = other;
1300 other = tmp;
1301 }
1302 }
1303
1304 //
1305 // non-standard:
1306 //
1307
1308 template< class T >
1309 variant_constexpr std::size_t index_of() const variant_noexcept
1310 {
1311 return to_size_t( detail::typelist_index_of<variant_types, typename detail::remove_cv<T>::type >::value );
1312 }
1313
1314 template< class T >
1315 T & get()
1316 {
1317 const std::size_t i = index_of<T>();
1318
1319 if ( i != index() || i == max_index() )
1320 {
1321 throw bad_variant_access();
1322 }
1323
1324 return *as<T>();
1325 }
1326
1327 template< class T >
1328 T const & get() const
1329 {
1330 const std::size_t i = index_of<T>();
1331
1332 if ( i != index() || i == max_index() )
1333 {
1334 throw bad_variant_access();
1335 }
1336
1337 return *as<const T>();
1338 }
1339
1340 template< std::size_t K >
1341 typename variant_alternative< K, variant >::type &
1342 get()
1343 {
1344 return this->template get< typename detail::typelist_type_at< variant_types, K >::type >();
1345 }
1346
1347 template< std::size_t K >
1348 typename variant_alternative< K, variant >::type const &
1349 get() const
1350 {
1351 return this->template get< typename detail::typelist_type_at< variant_types, K >::type >();
1352 }
1353
1354private:
1355 typedef typename helper_type::type_index_t type_index_t;
1356
1357 void * ptr() variant_noexcept
1358 {
1359 return &data;
1360 }
1361
1362 void const * ptr() const variant_noexcept
1363 {
1364 return &data;
1365 }
1366
1367 template< class U >
1368 U * as()
1369 {
1370 return reinterpret_cast<U*>( ptr() );
1371 }
1372
1373 template< class U >
1374 U const * as() const
1375 {
1376 return reinterpret_cast<U const *>( ptr() );
1377 }
1378
1379 template< class U >
1380 static std::size_t to_size_t( U index )
1381 {
1382 return static_cast<std::size_t >( index );
1383 }
1384
1385 variant_constexpr std::size_t max_index() const variant_noexcept
1386 {
1387 return data_size;
1388 }
1389
1390 variant_constexpr type_index_t variant_npos_internal() const variant_noexcept
1391 {
1392 return static_cast<type_index_t>( -1 );
1393 }
1394
1395 variant & copy_assign( variant const & other )
1396 {
1397 if ( valueless_by_exception() && other.valueless_by_exception() )
1398 {
1399 // no effect
1400 }
1401 else if ( ! valueless_by_exception() && other.valueless_by_exception() )
1402 {
1403 helper_type::destroy( type_index, ptr() );
1404 type_index = variant_npos_internal();
1405 }
1406 else if ( index() == other.index() )
1407 {
1408 type_index = helper_type::copy( other.type_index, other.ptr(), ptr() );
1409 }
1410 else
1411 {
1412 // alas exception safety with pre-C++11 needs an extra copy:
1413
1414 variant tmp( other );
1415 helper_type::destroy( type_index, ptr() );
1416 type_index = variant_npos_internal();
1417#if variant_CPP11_OR_GREATER
1418 type_index = helper_type::move( other.type_index, tmp.ptr(), ptr() );
1419#else
1420 type_index = helper_type::copy( other.type_index, tmp.ptr(), ptr() );
1421#endif
1422 }
1423 return *this;
1424 }
1425
1426#if variant_CPP11_OR_GREATER
1427
1428 variant & move_assign( variant && other )
1429 {
1430 if ( valueless_by_exception() && other.valueless_by_exception() )
1431 {
1432 // no effect
1433 }
1434 else if ( ! valueless_by_exception() && other.valueless_by_exception() )
1435 {
1436 helper_type::destroy( type_index, ptr() );
1437 type_index = variant_npos_internal();
1438 }
1439 else if ( index() == other.index() )
1440 {
1441 type_index = helper_type::move( other.type_index, other.ptr(), ptr() );
1442 }
1443 else
1444 {
1445 helper_type::destroy( type_index, ptr() );
1446 type_index = variant_npos_internal();
1447 type_index = helper_type::move( other.type_index, other.ptr(), ptr() );
1448 }
1449 return *this;
1450 }
1451
1452 template< class T, std::size_t K >
1453 variant & move_assign_value( T && value )
1454 {
1455 if( index() == K )
1456 {
1457 *as<T>() = std::forward<T>( value );
1458 }
1459 else
1460 {
1461 helper_type::destroy( type_index, ptr() );
1462 type_index = variant_npos_internal();
1463 new( ptr() ) T( std::forward<T>( value ) );
1464 type_index = K;
1465 }
1466 return *this;
1467 }
1468#else
1469 template< class T, std::size_t K >
1470 variant & copy_assign_value( T const & value )
1471 {
1472 if( index() == K )
1473 {
1474 *as<T>() = value;
1475 }
1476 else
1477 {
1478 helper_type::destroy( type_index, ptr() );
1479 type_index = variant_npos_internal();
1480 new( ptr() ) T( value );
1481 type_index = K;
1482 }
1483 return *this;
1484 }
1485
1486#endif // variant_CPP11_OR_GREATER
1487
1488 void swap_value( type_index_t index, variant & other )
1489 {
1490 using std::swap;
1491 switch( index )
1492 {
1493 case 0: swap( this->get<0>(), other.get<0>() ); break;
1494 case 1: swap( this->get<1>(), other.get<1>() ); break;
1495 case 2: swap( this->get<2>(), other.get<2>() ); break;
1496 case 3: swap( this->get<3>(), other.get<3>() ); break;
1497 case 4: swap( this->get<4>(), other.get<4>() ); break;
1498 case 5: swap( this->get<5>(), other.get<5>() ); break;
1499 case 6: swap( this->get<6>(), other.get<6>() ); break;
1500 case 7: swap( this->get<7>(), other.get<7>() ); break;
1501 case 8: swap( this->get<8>(), other.get<8>() ); break;
1502 case 9: swap( this->get<9>(), other.get<9>() ); break;
1503 case 10: swap( this->get<10>(), other.get<10>() ); break;
1504 case 11: swap( this->get<11>(), other.get<11>() ); break;
1505 case 12: swap( this->get<12>(), other.get<12>() ); break;
1506 case 13: swap( this->get<13>(), other.get<13>() ); break;
1507 case 14: swap( this->get<14>(), other.get<14>() ); break;
1508 case 15: swap( this->get<15>(), other.get<15>() ); break;
1509
1510 }
1511 }
1512
1513private:
1514 enum { data_size = detail::typelist_max< variant_types >::value };
1515
1516#if variant_CPP11_OR_GREATER
1517
1518 enum { data_align = detail::typelist_max_alignof< variant_types >::value };
1519
1520 using aligned_storage_t = typename std::aligned_storage< data_size, data_align >::type;
1521 aligned_storage_t data;
1522
1523#elif variant_CONFIG_MAX_ALIGN_HACK
1524
1525 typedef union { unsigned char data[ data_size ]; } aligned_storage_t;
1526
1527 detail::max_align_t hack;
1528 aligned_storage_t data;
1529
1530#else
1531 typedef typename detail::typelist_max< variant_types >::type max_type;
1532
1533 typedef variant_ALIGN_AS( max_type ) align_as_type;
1534
1535 typedef union { align_as_type data[ 1 + ( data_size - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
1536 aligned_storage_t data;
1537
1538// # undef variant_ALIGN_AS
1539
1540#endif // variant_CONFIG_MAX_ALIGN_HACK
1541
1542 type_index_t type_index;
1543};
1544
1545template< class T, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1546inline bool holds_alternative( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v ) variant_noexcept
1547{
1548 return v.index() == v.template index_of<T>();
1549}
1550
1551template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1552inline R & get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> & v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) )
1553{
1554 return v.template get<R>();
1555}
1556
1557template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1558inline R const & get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) )
1559{
1560 return v.template get<R>();
1561}
1562
1563template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1564inline typename variant_alternative< K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::type &
1565get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> & v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) )
1566{
1567 if ( K != v.index() )
1568 {
1569 throw bad_variant_access();
1570 }
1571
1572 return v.template get<K>();
1573}
1574
1575template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1576inline typename variant_alternative< K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::type const &
1577get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) )
1578{
1579 if ( K != v.index() )
1580 {
1581 throw bad_variant_access();
1582 }
1583
1584 return v.template get<K>();
1585}
1586
1587#if variant_CPP11_OR_GREATER
1588
1589template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1590inline R && get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> && v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) )
1591{
1592 return std::move(v.template get<R>());
1593}
1594
1595template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1596inline R const && get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const && v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) )
1597{
1598 return std::move(v.template get<R>());
1599}
1600
1601template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1602inline typename variant_alternative< K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::type &&
1603get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> && v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) )
1604{
1605 if ( K != v.index() )
1606 {
1607 throw bad_variant_access();
1608 }
1609
1610 return std::move(v.template get<K>());
1611}
1612
1613template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1614inline typename variant_alternative< K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::type const &&
1615get( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const && v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) )
1616{
1617 if ( K != v.index() )
1618 {
1619 throw bad_variant_access();
1620 }
1621
1622 return std::move(v.template get<K>());
1623}
1624
1625#endif // variant_CPP11_OR_GREATER
1626
1627template< class T, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1628inline typename detail::add_pointer<T>::type
1629get_if( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> * pv, nonstd_lite_in_place_type_t(T) = nonstd_lite_in_place_type(T) )
1630{
1631 return ( pv->index() == pv->template index_of<T>() ) ? &get<T>( *pv ) : variant_nullptr;
1632}
1633
1634template< class T, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1635inline typename detail::add_pointer<const T>::type
1636get_if( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const * pv, nonstd_lite_in_place_type_t(T) = nonstd_lite_in_place_type(T))
1637{
1638 return ( pv->index() == pv->template index_of<T>() ) ? &get<T>( *pv ) : variant_nullptr;
1639}
1640
1641template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1642inline typename detail::add_pointer< typename variant_alternative<K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::type >::type
1643get_if( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> * pv, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) )
1644{
1645 return ( pv->index() == K ) ? &get<K>( *pv ) : variant_nullptr;
1646}
1647
1648template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1649inline typename detail::add_pointer< const typename variant_alternative<K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::type >::type
1650get_if( variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const * pv, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) )
1651{
1652 return ( pv->index() == K ) ? &get<K>( *pv ) : variant_nullptr;
1653}
1654
1655template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
1656inline void swap(
1657 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> & a,
1658 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> & b ) variant_noexcept
1659{
1660 a.swap( b );
1661}
1662
1663// Variant 'visitor' implementation
1664
1665namespace detail
1666{
1667
1668template< typename R, typename VT >
1669struct VisitorApplicatorImpl
1670{
1671 template< typename Visitor, typename T >
1672 static R apply(Visitor const& v, T const& arg)
1673 {
1674 return v(arg);
1675 }
1676};
1677
1678template< typename R, typename VT >
1679struct VisitorApplicatorImpl<R, TX<VT> >
1680{
1681 template< typename Visitor, typename T >
1682 static R apply(Visitor const&, T)
1683 {
1684 return R();
1685 }
1686};
1687
1688template<typename R>
1689struct VisitorApplicator;
1690
1691template< typename R, typename Visitor, typename V1 >
1692struct VisitorUnwrapper;
1693
1694#if variant_CPP11_OR_GREATER
1695template< size_t NumVars, typename R, typename Visitor, typename ... T >
1696#else
1697template< size_t NumVars, typename R, typename Visitor, typename T1, typename T2 = S0, typename T3 = S0, typename T4 = S0, typename T5 = S0 >
1698#endif
1699struct TypedVisitorUnwrapper;
1700
1701template< typename R, typename Visitor, typename T2 >
1702struct TypedVisitorUnwrapper<2, R, Visitor, T2>
1703{
1704 const Visitor& visitor;
1705 T2 const& val2;
1706
1707 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_)
1708 : visitor(visitor_)
1709 , val2(val2_)
1710
1711 {
1712 }
1713
1714 template<typename T>
1715 R operator()(const T& val1) const
1716 {
1717 return visitor(val1, val2);
1718 }
1719};
1720
1721template< typename R, typename Visitor, typename T2, typename T3 >
1722struct TypedVisitorUnwrapper<3, R, Visitor, T2, T3>
1723{
1724 const Visitor& visitor;
1725 T2 const& val2;
1726 T3 const& val3;
1727
1728 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_, T3 const& val3_)
1729 : visitor(visitor_)
1730 , val2(val2_)
1731 , val3(val3_)
1732
1733 {
1734 }
1735
1736 template<typename T>
1737 R operator()(const T& val1) const
1738 {
1739 return visitor(val1, val2, val3);
1740 }
1741};
1742
1743template< typename R, typename Visitor, typename T2, typename T3, typename T4 >
1744struct TypedVisitorUnwrapper<4, R, Visitor, T2, T3, T4>
1745{
1746 const Visitor& visitor;
1747 T2 const& val2;
1748 T3 const& val3;
1749 T4 const& val4;
1750
1751 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_, T3 const& val3_, T4 const& val4_)
1752 : visitor(visitor_)
1753 , val2(val2_)
1754 , val3(val3_)
1755 , val4(val4_)
1756
1757 {
1758 }
1759
1760 template<typename T>
1761 R operator()(const T& val1) const
1762 {
1763 return visitor(val1, val2, val3, val4);
1764 }
1765};
1766
1767template< typename R, typename Visitor, typename T2, typename T3, typename T4, typename T5 >
1768struct TypedVisitorUnwrapper<5, R, Visitor, T2, T3, T4, T5>
1769{
1770 const Visitor& visitor;
1771 T2 const& val2;
1772 T3 const& val3;
1773 T4 const& val4;
1774 T5 const& val5;
1775
1776 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_, T3 const& val3_, T4 const& val4_, T5 const& val5_)
1777 : visitor(visitor_)
1778 , val2(val2_)
1779 , val3(val3_)
1780 , val4(val4_)
1781 , val5(val5_)
1782
1783 {
1784 }
1785
1786 template<typename T>
1787 R operator()(const T& val1) const
1788 {
1789 return visitor(val1, val2, val3, val4, val5);
1790 }
1791};
1792
1793
1794
1795template<typename R, typename Visitor, typename V2>
1796struct VisitorUnwrapper
1797{
1798 const Visitor& visitor;
1799 const V2& r;
1800
1801 VisitorUnwrapper(const Visitor& visitor_, const V2& r_)
1802 : visitor(visitor_)
1803 , r(r_)
1804 {
1805 }
1806
1807
1808 template< typename T1 >
1809 R operator()(T1 const& val1) const
1810 {
1811 typedef TypedVisitorUnwrapper<2, R, Visitor, T1> visitor_type;
1812 return VisitorApplicator<R>::apply(visitor_type(visitor, val1), r);
1813 }
1814
1815 template< typename T1, typename T2 >
1816 R operator()(T1 const& val1, T2 const& val2) const
1817 {
1818 typedef TypedVisitorUnwrapper<3, R, Visitor, T1, T2> visitor_type;
1819 return VisitorApplicator<R>::apply(visitor_type(visitor, val1, val2), r);
1820 }
1821
1822 template< typename T1, typename T2, typename T3 >
1823 R operator()(T1 const& val1, T2 const& val2, T3 const& val3) const
1824 {
1825 typedef TypedVisitorUnwrapper<4, R, Visitor, T1, T2, T3> visitor_type;
1826 return VisitorApplicator<R>::apply(visitor_type(visitor, val1, val2, val3), r);
1827 }
1828
1829 template< typename T1, typename T2, typename T3, typename T4 >
1830 R operator()(T1 const& val1, T2 const& val2, T3 const& val3, T4 const& val4) const
1831 {
1832 typedef TypedVisitorUnwrapper<5, R, Visitor, T1, T2, T3, T4> visitor_type;
1833 return VisitorApplicator<R>::apply(visitor_type(visitor, val1, val2, val3, val4), r);
1834 }
1835
1836 template< typename T1, typename T2, typename T3, typename T4, typename T5 >
1837 R operator()(T1 const& val1, T2 const& val2, T3 const& val3, T4 const& val4, T5 const& val5) const
1838 {
1839 typedef TypedVisitorUnwrapper<6, R, Visitor, T1, T2, T3, T4, T5> visitor_type;
1840 return VisitorApplicator<R>::apply(visitor_type(visitor, val1, val2, val3, val4, val5), r);
1841 }
1842
1843};
1844
1845
1846template<typename R>
1847struct VisitorApplicator
1848{
1849 template<typename Visitor, typename V1>
1850 static R apply(const Visitor& v, const V1& arg)
1851 {
1852 switch( arg.index() )
1853 {
1854 case 0: return apply_visitor<0>(v, arg);
1855 case 1: return apply_visitor<1>(v, arg);
1856 case 2: return apply_visitor<2>(v, arg);
1857 case 3: return apply_visitor<3>(v, arg);
1858 case 4: return apply_visitor<4>(v, arg);
1859 case 5: return apply_visitor<5>(v, arg);
1860 case 6: return apply_visitor<6>(v, arg);
1861 case 7: return apply_visitor<7>(v, arg);
1862 case 8: return apply_visitor<8>(v, arg);
1863 case 9: return apply_visitor<9>(v, arg);
1864 case 10: return apply_visitor<10>(v, arg);
1865 case 11: return apply_visitor<11>(v, arg);
1866 case 12: return apply_visitor<12>(v, arg);
1867 case 13: return apply_visitor<13>(v, arg);
1868 case 14: return apply_visitor<14>(v, arg);
1869 case 15: return apply_visitor<15>(v, arg);
1870
1871 default: return R();
1872 }
1873 }
1874
1875 template<size_t Idx, typename Visitor, typename V1>
1876 static R apply_visitor(const Visitor& v, const V1& arg)
1877 {
1878
1879#if variant_CPP11_OR_GREATER
1880 typedef typename variant_alternative<Idx, typename std::decay<V1>::type>::type value_type;
1881#else
1882 typedef typename variant_alternative<Idx, V1>::type value_type;
1883#endif
1884 return VisitorApplicatorImpl<R, value_type>::apply(v, get<Idx>(arg));
1885 }
1886
1887#if variant_CPP11_OR_GREATER
1888 template<typename Visitor, typename V1, typename V2, typename ... V>
1889 static R apply(const Visitor& v, const V1& arg1, const V2& arg2, const V ... args)
1890 {
1891 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
1892 Unwrapper unwrapper(v, arg1);
1893 return apply(unwrapper, arg2, args ...);
1894 }
1895#else
1896
1897 template< typename Visitor, typename V1, typename V2 >
1898 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2)
1899 {
1900 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
1901 Unwrapper unwrapper(v, arg1);
1902 return apply(unwrapper, arg2);
1903 }
1904
1905 template< typename Visitor, typename V1, typename V2, typename V3 >
1906 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3)
1907 {
1908 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
1909 Unwrapper unwrapper(v, arg1);
1910 return apply(unwrapper, arg2, arg3);
1911 }
1912
1913 template< typename Visitor, typename V1, typename V2, typename V3, typename V4 >
1914 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4)
1915 {
1916 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
1917 Unwrapper unwrapper(v, arg1);
1918 return apply(unwrapper, arg2, arg3, arg4);
1919 }
1920
1921 template< typename Visitor, typename V1, typename V2, typename V3, typename V4, typename V5 >
1922 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4, V5 const& arg5)
1923 {
1924 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
1925 Unwrapper unwrapper(v, arg1);
1926 return apply(unwrapper, arg2, arg3, arg4, arg5);
1927 }
1928
1929#endif
1930};
1931
1932#if variant_CPP11_OR_GREATER
1933template< size_t NumVars, typename Visitor, typename ... V >
1934struct VisitorImpl
1935{
1936 typedef decltype(std::declval<Visitor>()(get<0>(static_cast<const V&>(std::declval<V>()))...)) result_type;
1937 typedef VisitorApplicator<result_type> applicator_type;
1938};
1939#endif
1940} // detail
1941
1942#if variant_CPP11_OR_GREATER
1943// No perfect forwarding here in order to simplify code
1944template< typename Visitor, typename ... V >
1945inline auto visit(Visitor const& v, V const& ... vars) -> typename detail::VisitorImpl<sizeof ... (V), Visitor, V... > ::result_type
1946{
1947 typedef detail::VisitorImpl<sizeof ... (V), Visitor, V... > impl_type;
1948 return impl_type::applicator_type::apply(v, vars...);
1949}
1950#else
1951
1952template< typename R, typename Visitor, typename V1 >
1953inline R visit(const Visitor& v, V1 const& arg1)
1954{
1955 return detail::VisitorApplicator<R>::apply(v, arg1);
1956}
1957
1958template< typename R, typename Visitor, typename V1, typename V2 >
1959inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2)
1960{
1961 return detail::VisitorApplicator<R>::apply(v, arg1, arg2);
1962}
1963
1964template< typename R, typename Visitor, typename V1, typename V2, typename V3 >
1965inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3)
1966{
1967 return detail::VisitorApplicator<R>::apply(v, arg1, arg2, arg3);
1968}
1969
1970template< typename R, typename Visitor, typename V1, typename V2, typename V3, typename V4 >
1971inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4)
1972{
1973 return detail::VisitorApplicator<R>::apply(v, arg1, arg2, arg3, arg4);
1974}
1975
1976template< typename R, typename Visitor, typename V1, typename V2, typename V3, typename V4, typename V5 >
1977inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4, V5 const& arg5)
1978{
1979 return detail::VisitorApplicator<R>::apply(v, arg1, arg2, arg3, arg4, arg5);
1980}
1981
1982#endif
1983
1984
1985namespace detail {
1986
1987template< class Variant >
1988struct Comparator
1989{
1990 static inline bool equal( Variant const & v, Variant const & w )
1991 {
1992 switch( v.index() )
1993 {
1994 case 0: return get<0>( v ) == get<0>( w );
1995 case 1: return get<1>( v ) == get<1>( w );
1996 case 2: return get<2>( v ) == get<2>( w );
1997 case 3: return get<3>( v ) == get<3>( w );
1998 case 4: return get<4>( v ) == get<4>( w );
1999 case 5: return get<5>( v ) == get<5>( w );
2000 case 6: return get<6>( v ) == get<6>( w );
2001 case 7: return get<7>( v ) == get<7>( w );
2002 case 8: return get<8>( v ) == get<8>( w );
2003 case 9: return get<9>( v ) == get<9>( w );
2004 case 10: return get<10>( v ) == get<10>( w );
2005 case 11: return get<11>( v ) == get<11>( w );
2006 case 12: return get<12>( v ) == get<12>( w );
2007 case 13: return get<13>( v ) == get<13>( w );
2008 case 14: return get<14>( v ) == get<14>( w );
2009 case 15: return get<15>( v ) == get<15>( w );
2010
2011 default: return false;
2012 }
2013 }
2014
2015 static inline bool less_than( Variant const & v, Variant const & w )
2016 {
2017 switch( v.index() )
2018 {
2019 case 0: return get<0>( v ) < get<0>( w );
2020 case 1: return get<1>( v ) < get<1>( w );
2021 case 2: return get<2>( v ) < get<2>( w );
2022 case 3: return get<3>( v ) < get<3>( w );
2023 case 4: return get<4>( v ) < get<4>( w );
2024 case 5: return get<5>( v ) < get<5>( w );
2025 case 6: return get<6>( v ) < get<6>( w );
2026 case 7: return get<7>( v ) < get<7>( w );
2027 case 8: return get<8>( v ) < get<8>( w );
2028 case 9: return get<9>( v ) < get<9>( w );
2029 case 10: return get<10>( v ) < get<10>( w );
2030 case 11: return get<11>( v ) < get<11>( w );
2031 case 12: return get<12>( v ) < get<12>( w );
2032 case 13: return get<13>( v ) < get<13>( w );
2033 case 14: return get<14>( v ) < get<14>( w );
2034 case 15: return get<15>( v ) < get<15>( w );
2035
2036 default: return false;
2037 }
2038 }
2039};
2040
2041} //namespace detail
2042
2043template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
2044inline bool operator==(
2045 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v,
2046 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & w )
2047{
2048 if ( v.index() != w.index() ) return false;
2049 else if ( v.valueless_by_exception() ) return true;
2050 else return detail::Comparator< variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::equal( v, w );
2051}
2052
2053template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
2054inline bool operator!=(
2055 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v,
2056 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & w )
2057{
2058 return ! ( v == w );
2059}
2060
2061template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
2062inline bool operator<(
2063 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v,
2064 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & w )
2065{
2066 if ( w.valueless_by_exception() ) return false;
2067 else if ( v.valueless_by_exception() ) return true;
2068 else if ( v.index() < w.index() ) return true;
2069 else if ( v.index() > w.index() ) return false;
2070 else return detail::Comparator< variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >::less_than( v, w );
2071}
2072
2073template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
2074inline bool operator>(
2075 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v,
2076 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & w )
2077{
2078 return w < v;
2079}
2080
2081template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
2082inline bool operator<=(
2083 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v,
2084 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & w )
2085{
2086 return ! ( v > w );
2087}
2088
2089template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
2090inline bool operator>=(
2091 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v,
2092 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & w )
2093{
2094 return ! ( v < w );
2095}
2096
2097} // namespace variants
2098
2099using namespace variants;
2100
2101} // namespace nonstd
2102
2103#if variant_CPP11_OR_GREATER
2104
2105// specialize the std::hash algorithm:
2106
2107namespace std {
2108
2109template<>
2110struct hash< nonstd::monostate >
2111{
2112 std::size_t operator()( nonstd::monostate ) const variant_noexcept
2113 {
2114 return 42;
2115 }
2116};
2117
2118template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 >
2119struct hash< nonstd::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
2120{
2121 std::size_t operator()( nonstd::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> const & v ) const variant_noexcept
2122 {
2123 return nonstd::variants::detail::hash( v );
2124 }
2125};
2126
2127} //namespace std
2128
2129#endif // variant_CPP11_OR_GREATER
2130
2131#if variant_BETWEEN( variant_COMPILER_MSVC_VER, 1300, 1900 )
2132# pragma warning( pop )
2133#endif
2134
2135#endif // variant_USES_STD_VARIANT
2136
2137#endif // NONSTD_VARIANT_LITE_HPP