1#ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
2#define BOOST_VARIANT2_VARIANT_HPP_INCLUDED
3
4// Copyright 2017-2019 Peter Dimov.
5//
6// Distributed under the Boost Software License, Version 1.0.
7//
8// See accompanying file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt
10
11#if defined(_MSC_VER) && _MSC_VER < 1910
12# pragma warning( push )
13# pragma warning( disable: 4521 4522 ) // multiple copy operators
14#endif
15
16#include <boost/mp11.hpp>
17#include <boost/assert.hpp>
18#include <boost/assert/source_location.hpp>
19#include <boost/config.hpp>
20#include <boost/config/workaround.hpp>
21#include <cstddef>
22#include <type_traits>
23#include <exception>
24#include <utility>
25#include <typeindex> // std::hash
26#include <iosfwd>
27#include <cstdint>
28#include <cerrno>
29
30//
31
32namespace boost
33{
34
35#ifdef BOOST_NO_EXCEPTIONS
36
37BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
38
39#endif
40
41template<class T> struct hash;
42
43namespace variant2
44{
45
46// bad_variant_access
47
48class bad_variant_access: public std::exception
49{
50public:
51
52 bad_variant_access() noexcept
53 {
54 }
55
56 char const * what() const noexcept
57 {
58 return "bad_variant_access";
59 }
60};
61
62namespace detail
63{
64
65BOOST_NORETURN inline void throw_bad_variant_access()
66{
67#ifdef BOOST_NO_EXCEPTIONS
68
69 boost::throw_exception( bad_variant_access() );
70
71#else
72
73 throw bad_variant_access();
74
75#endif
76}
77
78} // namespace detail
79
80// monostate
81
82struct monostate
83{
84};
85
86#if !BOOST_WORKAROUND(BOOST_MSVC, < 1940)
87
88constexpr bool operator<(monostate, monostate) noexcept { return false; }
89constexpr bool operator>(monostate, monostate) noexcept { return false; }
90constexpr bool operator<=(monostate, monostate) noexcept { return true; }
91constexpr bool operator>=(monostate, monostate) noexcept { return true; }
92constexpr bool operator==(monostate, monostate) noexcept { return true; }
93constexpr bool operator!=(monostate, monostate) noexcept { return false; }
94
95#else
96
97constexpr bool operator<(monostate const&, monostate const&) noexcept { return false; }
98constexpr bool operator>(monostate const&, monostate const&) noexcept { return false; }
99constexpr bool operator<=(monostate const&, monostate const&) noexcept { return true; }
100constexpr bool operator>=(monostate const&, monostate const&) noexcept { return true; }
101constexpr bool operator==(monostate const&, monostate const&) noexcept { return true; }
102constexpr bool operator!=(monostate const&, monostate const&) noexcept { return false; }
103
104#endif
105
106// variant forward declaration
107
108template<class... T> class variant;
109
110// variant_size
111
112template<class T> struct variant_size
113{
114};
115
116template<class T> struct variant_size<T const>: variant_size<T>
117{
118};
119
120template<class T> struct variant_size<T volatile>: variant_size<T>
121{
122};
123
124template<class T> struct variant_size<T const volatile>: variant_size<T>
125{
126};
127
128template<class T> struct variant_size<T&>: variant_size<T>
129{
130};
131
132template<class T> struct variant_size<T&&>: variant_size<T>
133{
134};
135
136#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
137
138template <class T> /*inline*/ constexpr std::size_t variant_size_v = variant_size<T>::value;
139
140#endif
141
142template <class... T> struct variant_size<variant<T...>>: mp11::mp_size<variant<T...>>
143{
144};
145
146// variant_alternative
147
148template<std::size_t I, class T> struct variant_alternative;
149
150template<std::size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type;
151
152#if BOOST_WORKAROUND(BOOST_GCC, < 40900)
153
154namespace detail
155{
156
157template<std::size_t I, class T, bool E> struct variant_alternative_impl
158{
159};
160
161template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>, true>
162{
163 using type = mp11::mp_at_c<variant<T...>, I>;
164};
165
166template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const, true>: std::add_const< mp11::mp_at_c<variant<T...>, I> >
167{
168};
169
170template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile, true>: std::add_volatile< mp11::mp_at_c<variant<T...>, I> >
171{
172};
173
174template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile, true>: std::add_cv< mp11::mp_at_c<variant<T...>, I> >
175{
176};
177
178template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> >
179{
180};
181
182template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> const >
183{
184};
185
186template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> volatile >
187{
188};
189
190template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile&, true>: std::add_lvalue_reference< mp11::mp_at_c<variant<T...>, I> const volatile >
191{
192};
193
194template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> >
195{
196};
197
198template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> const >
199{
200};
201
202template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> volatile&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> volatile >
203{
204};
205
206template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...> const volatile&&, true>: std::add_rvalue_reference< mp11::mp_at_c<variant<T...>, I> const volatile >
207{
208};
209
210} // namespace detail
211
212template<std::size_t I, class T> struct variant_alternative
213{
214};
215
216template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>: public detail::variant_alternative_impl<I, variant<T...>, (I < sizeof...(T))>
217{
218};
219
220template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const>: public detail::variant_alternative_impl<I, variant<T...> const, (I < sizeof...(T))>
221{
222};
223
224template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile>: public detail::variant_alternative_impl<I, variant<T...> volatile, (I < sizeof...(T))>
225{
226};
227
228template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile>: public detail::variant_alternative_impl<I, variant<T...> const volatile, (I < sizeof...(T))>
229{
230};
231
232template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&>: public detail::variant_alternative_impl<I, variant<T...>&, (I < sizeof...(T))>
233{
234};
235
236template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const&>: public detail::variant_alternative_impl<I, variant<T...> const&, (I < sizeof...(T))>
237{
238};
239
240template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile&>: public detail::variant_alternative_impl<I, variant<T...> volatile&, (I < sizeof...(T))>
241{
242};
243
244template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile&>: public detail::variant_alternative_impl<I, variant<T...> const volatile&, (I < sizeof...(T))>
245{
246};
247
248template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&&>: public detail::variant_alternative_impl<I, variant<T...>&&, (I < sizeof...(T))>
249{
250};
251
252template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const&&>: public detail::variant_alternative_impl<I, variant<T...> const&&, (I < sizeof...(T))>
253{
254};
255
256template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> volatile&&>: public detail::variant_alternative_impl<I, variant<T...> volatile&&, (I < sizeof...(T))>
257{
258};
259
260template<std::size_t I, class... T> struct variant_alternative<I, variant<T...> const volatile&&>: public detail::variant_alternative_impl<I, variant<T...> const volatile&&, (I < sizeof...(T))>
261{
262};
263
264#else
265
266namespace detail
267{
268
269#if defined( BOOST_MP11_VERSION ) && BOOST_MP11_VERSION >= 107000
270
271template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke_q<Q, variant_alternative_t<I::value, T>>;
272
273#else
274
275template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke<Q, variant_alternative_t<I::value, T>>;
276
277#endif
278
279} // namespace detail
280
281template<std::size_t I, class T> struct variant_alternative
282{
283};
284
285template<std::size_t I, class T> struct variant_alternative<I, T const>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_const>>
286{
287};
288
289template<std::size_t I, class T> struct variant_alternative<I, T volatile>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_volatile>>
290{
291};
292
293template<std::size_t I, class T> struct variant_alternative<I, T const volatile>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_cv>>
294{
295};
296
297template<std::size_t I, class T> struct variant_alternative<I, T&>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_lvalue_reference>>
298{
299};
300
301template<std::size_t I, class T> struct variant_alternative<I, T&&>: mp11::mp_defer<detail::var_alt_impl, mp11::mp_size_t<I>, T, mp11::mp_quote_trait<std::add_rvalue_reference>>
302{
303};
304
305template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>: mp11::mp_defer<mp11::mp_at, variant<T...>, mp11::mp_size_t<I>>
306{
307};
308
309#endif
310
311// variant_npos
312
313constexpr std::size_t variant_npos = ~static_cast<std::size_t>( 0 );
314
315// holds_alternative
316
317template<class U, class... T> constexpr bool holds_alternative( variant<T...> const& v ) noexcept
318{
319 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
320 return v.index() == mp11::mp_find<variant<T...>, U>::value;
321}
322
323// get (index)
324
325template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& get(variant<T...>& v)
326{
327 static_assert( I < sizeof...(T), "Index out of bounds" );
328 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
329}
330
331template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& get(variant<T...>&& v)
332{
333 static_assert( I < sizeof...(T), "Index out of bounds" );
334
335#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
336
337 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
338
339#else
340
341 if( v.index() != I ) detail::throw_bad_variant_access();
342 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
343
344#endif
345}
346
347template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& get(variant<T...> const& v)
348{
349 static_assert( I < sizeof...(T), "Index out of bounds" );
350 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
351}
352
353template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& get(variant<T...> const&& v)
354{
355 static_assert( I < sizeof...(T), "Index out of bounds" );
356
357#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
358
359 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
360
361#else
362
363 if( v.index() != I ) detail::throw_bad_variant_access();
364 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
365
366#endif
367}
368
369// unsafe_get
370
371#if !defined(BOOST_NO_CXX14_CONSTEXPR)
372# define BOOST_VARIANT2_CX14_ASSERT(expr) BOOST_ASSERT(expr);
373#else
374# define BOOST_VARIANT2_CX14_ASSERT(expr)
375#endif
376
377template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& unsafe_get(variant<T...>& v)
378{
379 static_assert( I < sizeof...(T), "Index out of bounds" );
380
381 BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
382
383 return v._get_impl( mp11::mp_size_t<I>() );
384}
385
386template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& unsafe_get(variant<T...>&& v)
387{
388 static_assert( I < sizeof...(T), "Index out of bounds" );
389
390 BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
391
392 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
393}
394
395template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& unsafe_get(variant<T...> const& v)
396{
397 static_assert( I < sizeof...(T), "Index out of bounds" );
398
399 BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
400
401 return v._get_impl( mp11::mp_size_t<I>() );
402}
403
404template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& unsafe_get(variant<T...> const&& v)
405{
406 static_assert( I < sizeof...(T), "Index out of bounds" );
407
408 BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
409
410 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
411}
412
413// get (type)
414
415template<class U, class... T> constexpr U& get(variant<T...>& v)
416{
417 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
418
419 using I = mp11::mp_find<variant<T...>, U>;
420
421 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
422}
423
424template<class U, class... T> constexpr U&& get(variant<T...>&& v)
425{
426 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
427
428 using I = mp11::mp_find<variant<T...>, U>;
429
430#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
431
432 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
433
434#else
435
436 if( v.index() != I::value ) detail::throw_bad_variant_access();
437 return std::move( v._get_impl( I() ) );
438
439#endif
440}
441
442template<class U, class... T> constexpr U const& get(variant<T...> const& v)
443{
444 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
445
446 using I = mp11::mp_find<variant<T...>, U>;
447
448 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
449}
450
451template<class U, class... T> constexpr U const&& get(variant<T...> const&& v)
452{
453 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
454
455 using I = mp11::mp_find<variant<T...>, U>;
456
457#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
458
459 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
460
461#else
462
463 if( v.index() != I::value ) detail::throw_bad_variant_access();
464 return std::move( v._get_impl( I() ) );
465
466#endif
467}
468
469// get_if
470
471template<std::size_t I, class... T> constexpr typename std::add_pointer<variant_alternative_t<I, variant<T...>>>::type get_if(variant<T...>* v) noexcept
472{
473 static_assert( I < sizeof...(T), "Index out of bounds" );
474 return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
475}
476
477template<std::size_t I, class... T> constexpr typename std::add_pointer<const variant_alternative_t<I, variant<T...>>>::type get_if(variant<T...> const * v) noexcept
478{
479 static_assert( I < sizeof...(T), "Index out of bounds" );
480 return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
481}
482
483template<class U, class... T> constexpr typename std::add_pointer<U>::type get_if(variant<T...>* v) noexcept
484{
485 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
486
487 using I = mp11::mp_find<variant<T...>, U>;
488
489 return v && v->index() == I::value? &v->_get_impl( I() ): 0;
490}
491
492template<class U, class... T> constexpr typename std::add_pointer<U const>::type get_if(variant<T...> const * v) noexcept
493{
494 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
495
496 using I = mp11::mp_find<variant<T...>, U>;
497
498 return v && v->index() == I::value? &v->_get_impl( I() ): 0;
499}
500
501//
502
503namespace detail
504{
505
506// trivially_*
507
508#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
509
510template<class T> struct is_trivially_copy_constructible: mp11::mp_bool<std::is_copy_constructible<T>::value && std::has_trivial_copy_constructor<T>::value>
511{
512};
513
514template<class T> struct is_trivially_copy_assignable: mp11::mp_bool<std::is_copy_assignable<T>::value && std::has_trivial_copy_assign<T>::value>
515{
516};
517
518template<class T> struct is_trivially_move_constructible: mp11::mp_bool<std::is_move_constructible<T>::value && std::is_trivial<T>::value>
519{
520};
521
522template<class T> struct is_trivially_move_assignable: mp11::mp_bool<std::is_move_assignable<T>::value && std::is_trivial<T>::value>
523{
524};
525
526#else
527
528using std::is_trivially_copy_constructible;
529using std::is_trivially_copy_assignable;
530using std::is_trivially_move_constructible;
531using std::is_trivially_move_assignable;
532
533#endif
534
535// variant_storage
536
537template<class D, class... T> union variant_storage_impl;
538
539template<class... T> using variant_storage = variant_storage_impl<mp11::mp_all<std::is_trivially_destructible<T>...>, T...>;
540
541template<class D> union variant_storage_impl<D>
542{
543};
544
545// not all trivially destructible
546template<class T1, class... T> union variant_storage_impl<mp11::mp_false, T1, T...>
547{
548 T1 first_;
549 variant_storage<T...> rest_;
550
551 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
552 {
553 }
554
555 template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
556 {
557 }
558
559 ~variant_storage_impl()
560 {
561 }
562
563 template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a )
564 {
565 ::new( &first_ ) T1( std::forward<A>(a)... );
566 }
567
568 template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
569 {
570 rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
571 }
572
573 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
574 constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
575
576 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-1>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
577 template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
578};
579
580template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> union variant_storage_impl<mp11::mp_false, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>
581{
582 T0 t0_;
583 T1 t1_;
584 T2 t2_;
585 T3 t3_;
586 T4 t4_;
587 T5 t5_;
588 T6 t6_;
589 T7 t7_;
590 T8 t8_;
591 T9 t9_;
592
593 variant_storage<T...> rest_;
594
595 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
596 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
597 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
598 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
599 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
600 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
601 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
602 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
603 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
604 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
605
606 template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
607
608 ~variant_storage_impl()
609 {
610 }
611
612 template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
613 template<class... A> void emplace( mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
614 template<class... A> void emplace( mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
615 template<class... A> void emplace( mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
616 template<class... A> void emplace( mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
617 template<class... A> void emplace( mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
618 template<class... A> void emplace( mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
619 template<class... A> void emplace( mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
620 template<class... A> void emplace( mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
621 template<class... A> void emplace( mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
622
623 template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
624 {
625 rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
626 }
627
628 BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
629 constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
630
631 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
632 constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
633
634 BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
635 constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
636
637 BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
638 constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
639
640 BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
641 constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
642
643 BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
644 constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
645
646 BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
647 constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
648
649 BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
650 constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
651
652 BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
653 constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
654
655 BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
656 constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
657
658 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-10>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
659 template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-10> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
660};
661
662// all trivially destructible
663template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T...>
664{
665 T1 first_;
666 variant_storage<T...> rest_;
667
668 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
669 {
670 }
671
672 template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
673 {
674 }
675
676 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a )
677 {
678 ::new( &first_ ) T1( std::forward<A>(a)... );
679 }
680
681 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
682 {
683 rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
684 }
685
686 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
687 {
688#if defined(BOOST_GCC) && (__GNUC__ >= 7)
689# pragma GCC diagnostic push
690// False positive in at least GCC 7 and GCC 10 ASAN triggered by monostate (via result<void>)
691# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
692#if __GNUC__ >= 12
693// False positive in at least GCC 12 and GCC 13 ASAN and -Og triggered by monostate (via result<void>)
694# pragma GCC diagnostic ignored "-Wuninitialized"
695#endif
696#endif
697 *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
698
699#if defined(BOOST_GCC) && (__GNUC__ >= 7)
700# pragma GCC diagnostic pop
701#endif
702 }
703
704 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
705 {
706 this->emplace_impl( mp11::mp_all<detail::is_trivially_move_assignable<T1>, detail::is_trivially_move_assignable<T>...>(), mp11::mp_size_t<I>(), std::forward<A>(a)... );
707 }
708
709 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
710 constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
711
712 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-1>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
713 template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
714};
715
716template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> union variant_storage_impl<mp11::mp_true, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>
717{
718 T0 t0_;
719 T1 t1_;
720 T2 t2_;
721 T3 t3_;
722 T4 t4_;
723 T5 t5_;
724 T6 t6_;
725 T7 t7_;
726 T8 t8_;
727 T9 t9_;
728
729 variant_storage<T...> rest_;
730
731 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
732 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
733 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
734 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
735 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
736 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
737 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
738 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
739 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
740 template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
741
742 template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
743
744 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
745 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
746 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
747 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
748 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
749 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
750 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
751 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
752 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
753 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
754
755 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
756 {
757 rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
758 }
759
760 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
761 {
762 *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
763 }
764
765 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
766 {
767 this->emplace_impl( mp11::mp_all<
768 detail::is_trivially_move_assignable<T0>,
769 detail::is_trivially_move_assignable<T1>,
770 detail::is_trivially_move_assignable<T2>,
771 detail::is_trivially_move_assignable<T3>,
772 detail::is_trivially_move_assignable<T4>,
773 detail::is_trivially_move_assignable<T5>,
774 detail::is_trivially_move_assignable<T6>,
775 detail::is_trivially_move_assignable<T7>,
776 detail::is_trivially_move_assignable<T8>,
777 detail::is_trivially_move_assignable<T9>,
778 detail::is_trivially_move_assignable<T>...>(), mp11::mp_size_t<I>(), std::forward<A>(a)... );
779 }
780
781 BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
782 constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
783
784 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
785 constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
786
787 BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
788 constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
789
790 BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
791 constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
792
793 BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
794 constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
795
796 BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
797 constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
798
799 BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
800 constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
801
802 BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
803 constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
804
805 BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
806 constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
807
808 BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
809 constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
810
811 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-10>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
812 template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-10> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
813};
814
815// resolve_overload_*
816
817template<class... T> struct overload;
818
819template<> struct overload<>
820{
821 void operator()() const;
822};
823
824template<class T1, class... T> struct overload<T1, T...>: overload<T...>
825{
826 using overload<T...>::operator();
827 mp11::mp_identity<T1> operator()(T1) const;
828};
829
830#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
831
832template<class U, class... T> using resolve_overload_type_ = decltype( overload<T...>()(std::declval<U>()) );
833
834template<class U, class... T> struct resolve_overload_type_impl: mp11::mp_defer< resolve_overload_type_, U, T... >
835{
836};
837
838template<class U, class... T> using resolve_overload_type = typename resolve_overload_type_impl<U, T...>::type::type;
839
840#else
841
842template<class U, class... T> using resolve_overload_type = typename decltype( overload<T...>()(std::declval<U>()) )::type;
843
844#endif
845
846template<class U, class... T> using resolve_overload_index = mp11::mp_find<mp11::mp_list<T...>, resolve_overload_type<U, T...>>;
847
848// variant_base
849
850template<bool is_trivially_destructible, bool is_single_buffered, class... T> struct variant_base_impl;
851template<class... T> using variant_base = variant_base_impl<mp11::mp_all<std::is_trivially_destructible<T>...>::value, mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value, T...>;
852
853struct none {};
854
855// trivially destructible, single buffered
856template<class... T> struct variant_base_impl<true, true, T...>
857{
858 variant_storage<none, T...> st_;
859 unsigned ix_;
860
861 constexpr variant_base_impl(): st_( mp11::mp_size_t<0>() ), ix_( 0 )
862 {
863 }
864
865 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), ix_( I::value + 1 )
866 {
867 }
868
869 // requires: ix_ == 0
870 template<class I, class... A> void _replace( I, A&&... a )
871 {
872 ::new( &st_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
873 ix_ = I::value + 1;
874 }
875
876 constexpr std::size_t index() const noexcept
877 {
878 return ix_ - 1;
879 }
880
881 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
882 {
883 size_t const J = I+1;
884
885 BOOST_ASSERT( ix_ == J );
886
887 return st_.get( mp11::mp_size_t<J>() );
888 }
889
890 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
891 {
892 // size_t const J = I+1;
893
894 BOOST_VARIANT2_CX14_ASSERT( ix_ == I+1 )
895
896 return st_.get( mp11::mp_size_t<I+1>() );
897 }
898
899 template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, A&&... a )
900 {
901 static_assert( std::is_nothrow_constructible<U, A&&...>::value, "Logic error: U must be nothrow constructible from A&&..." );
902
903 st_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
904 ix_ = J;
905 }
906
907 template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, A&&... a )
908 {
909 static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
910
911 U tmp( std::forward<A>(a)... );
912
913 st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
914 ix_ = J;
915 }
916
917 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
918 {
919 std::size_t const J = I+1;
920 using U = mp11::mp_at_c<variant<T...>, I>;
921
922 this->emplace_impl<J, U>( std::is_nothrow_constructible<U, A&&...>(), std::forward<A>(a)... );
923 }
924
925 static constexpr bool uses_double_storage() noexcept
926 {
927 return false;
928 }
929};
930
931// trivially destructible, double buffered
932template<class... T> struct variant_base_impl<true, false, T...>
933{
934 variant_storage<none, T...> st_[ 2 ];
935 unsigned ix_;
936
937 constexpr variant_base_impl(): st_{ { mp11::mp_size_t<0>() }, { mp11::mp_size_t<0>() } }, ix_( 0 )
938 {
939 }
940
941 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { mp11::mp_size_t<0>() } }, ix_( ( I::value + 1 ) * 2 )
942 {
943 }
944
945 // requires: ix_ == 0
946 template<class I, class... A> void _replace( I, A&&... a )
947 {
948 ::new( &st_[ 0 ] ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
949 ix_ = ( I::value + 1 ) * 2;
950 }
951
952 constexpr std::size_t index() const noexcept
953 {
954 return ix_ / 2 - 1;
955 }
956
957 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
958 {
959 BOOST_ASSERT( index() == I );
960
961 size_t const J = I+1;
962
963 constexpr mp11::mp_size_t<J> j{};
964 return st_[ ix_ & 1 ].get( j );
965 }
966
967 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
968 {
969 BOOST_VARIANT2_CX14_ASSERT( index() == I )
970
971 // size_t const J = I+1;
972 // constexpr mp_size_t<J> j{};
973
974 return st_[ ix_ & 1 ].get( mp11::mp_size_t<I+1>() );
975 }
976
977 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
978 {
979 size_t const J = I+1;
980
981 unsigned i2 = 1 - ( ix_ & 1 );
982
983 st_[ i2 ].emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
984
985 ix_ = J * 2 + i2;
986 }
987
988 static constexpr bool uses_double_storage() noexcept
989 {
990 return true;
991 }
992};
993
994// not trivially destructible, single buffered
995template<class... T> struct variant_base_impl<false, true, T...>
996{
997 variant_storage<none, T...> st_;
998 unsigned ix_;
999
1000 constexpr variant_base_impl(): st_( mp11::mp_size_t<0>() ), ix_( 0 )
1001 {
1002 }
1003
1004 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), ix_( I::value + 1 )
1005 {
1006 }
1007
1008 // requires: ix_ == 0
1009 template<class I, class... A> void _replace( I, A&&... a )
1010 {
1011 ::new( &st_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
1012 ix_ = I::value + 1;
1013 }
1014
1015 //[&]( auto I ){
1016 // using U = mp_at_c<mp_list<none, T...>, I>;
1017 // st1_.get( I ).~U();
1018 //}
1019
1020 struct _destroy_L1
1021 {
1022 variant_base_impl * this_;
1023
1024 template<class I> void operator()( I ) const noexcept
1025 {
1026 using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
1027 this_->st_.get( I() ).~U();
1028 }
1029 };
1030
1031 void _destroy() noexcept
1032 {
1033 if( ix_ > 0 )
1034 {
1035 mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
1036 }
1037 }
1038
1039 ~variant_base_impl() noexcept
1040 {
1041 _destroy();
1042 }
1043
1044 constexpr std::size_t index() const noexcept
1045 {
1046 return ix_ - 1;
1047 }
1048
1049 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
1050 {
1051 size_t const J = I+1;
1052
1053 BOOST_ASSERT( ix_ == J );
1054
1055 return st_.get( mp11::mp_size_t<J>() );
1056 }
1057
1058 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
1059 {
1060 // size_t const J = I+1;
1061
1062 BOOST_VARIANT2_CX14_ASSERT( ix_ == I+1 )
1063
1064 return st_.get( mp11::mp_size_t<I+1>() );
1065 }
1066
1067 template<std::size_t I, class... A> void emplace( A&&... a )
1068 {
1069 size_t const J = I+1;
1070
1071 using U = mp11::mp_at_c<variant<T...>, I>;
1072
1073 static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
1074
1075 U tmp( std::forward<A>(a)... );
1076
1077 _destroy();
1078
1079 st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
1080 ix_ = J;
1081 }
1082
1083 static constexpr bool uses_double_storage() noexcept
1084 {
1085 return false;
1086 }
1087};
1088
1089// not trivially destructible, double buffered
1090template<class... T> struct variant_base_impl<false, false, T...>
1091{
1092#if defined(__GNUC__) && __GNUC__ < 11 && !defined(__clang__) && !defined(__INTEL_COMPILER)
1093
1094 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63707 :-(
1095
1096 variant_storage<none, T...> st1_, st2_;
1097 unsigned ix_;
1098
1099 constexpr variant_base_impl(): st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() ), ix_( 0 )
1100 {
1101 }
1102
1103 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() ), ix_( ( I::value + 1 ) * 2 )
1104 {
1105 }
1106
1107 BOOST_CXX14_CONSTEXPR variant_storage<none, T...>& storage( unsigned i2 ) noexcept
1108 {
1109 return i2 == 0? st1_: st2_;
1110 }
1111
1112 constexpr variant_storage<none, T...> const& storage( unsigned i2 ) const noexcept
1113 {
1114 return i2 == 0? st1_: st2_;
1115 }
1116
1117#else
1118
1119 variant_storage<none, T...> st_[ 2 ];
1120 unsigned ix_;
1121
1122 constexpr variant_base_impl(): st_{ { mp11::mp_size_t<0>() }, { mp11::mp_size_t<0>() } }, ix_( 0 )
1123 {
1124 }
1125
1126 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { mp11::mp_size_t<0>() } }, ix_( ( I::value + 1 ) * 2 )
1127 {
1128 }
1129
1130 BOOST_CXX14_CONSTEXPR variant_storage<none, T...>& storage( unsigned i2 ) noexcept
1131 {
1132 return st_[ i2 ];
1133 }
1134
1135 constexpr variant_storage<none, T...> const& storage( unsigned i2 ) const noexcept
1136 {
1137 return st_[ i2 ];
1138 }
1139
1140#endif
1141
1142 // requires: ix_ == 0
1143 template<class I, class... A> void _replace( I, A&&... a )
1144 {
1145 ::new( &storage( 0 ) ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
1146 ix_ = ( I::value + 1 ) * 2;
1147 }
1148
1149 //[&]( auto I ){
1150 // using U = mp_at_c<mp_list<none, T...>, I>;
1151 // st1_.get( I ).~U();
1152 //}
1153
1154 struct _destroy_L1
1155 {
1156 variant_base_impl * this_;
1157 unsigned i2_;
1158
1159 template<class I> void operator()( I ) const noexcept
1160 {
1161 using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
1162 this_->storage( i2_ ).get( I() ).~U();
1163 }
1164 };
1165
1166 void _destroy() noexcept
1167 {
1168 mp11::mp_with_index<1 + sizeof...(T)>( ix_ / 2, _destroy_L1{ this, ix_ & 1 } );
1169 }
1170
1171 ~variant_base_impl() noexcept
1172 {
1173 _destroy();
1174 }
1175
1176 constexpr std::size_t index() const noexcept
1177 {
1178 return ix_ / 2 - 1;
1179 }
1180
1181 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
1182 {
1183 BOOST_ASSERT( index() == I );
1184
1185 size_t const J = I+1;
1186
1187 constexpr mp11::mp_size_t<J> j{};
1188 return storage( ix_ & 1 ).get( j );
1189 }
1190
1191 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
1192 {
1193 BOOST_VARIANT2_CX14_ASSERT( index() == I )
1194
1195 // size_t const J = I+1;
1196 // constexpr mp_size_t<J> j{};
1197
1198 return storage( ix_ & 1 ).get( mp11::mp_size_t<I+1>() );
1199 }
1200
1201 template<std::size_t I, class... A> void emplace( A&&... a )
1202 {
1203 size_t const J = I+1;
1204
1205 unsigned i2 = 1 - ( ix_ & 1 );
1206
1207 storage( i2 ).emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
1208 _destroy();
1209
1210 ix_ = J * 2 + i2;
1211 }
1212
1213 static constexpr bool uses_double_storage() noexcept
1214 {
1215 return true;
1216 }
1217};
1218
1219} // namespace detail
1220
1221// in_place_type_t
1222
1223template<class T> struct in_place_type_t
1224{
1225};
1226
1227#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
1228
1229template<class T> constexpr in_place_type_t<T> in_place_type{};
1230
1231#endif
1232
1233namespace detail
1234{
1235
1236template<class T> struct is_in_place_type: std::false_type {};
1237template<class T> struct is_in_place_type<in_place_type_t<T>>: std::true_type {};
1238
1239} // namespace detail
1240
1241// in_place_index_t
1242
1243template<std::size_t I> struct in_place_index_t
1244{
1245};
1246
1247#if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
1248
1249template<std::size_t I> constexpr in_place_index_t<I> in_place_index{};
1250
1251#endif
1252
1253namespace detail
1254{
1255
1256template<class T> struct is_in_place_index: std::false_type {};
1257template<std::size_t I> struct is_in_place_index<in_place_index_t<I>>: std::true_type {};
1258
1259} // namespace detail
1260
1261// is_nothrow_swappable
1262
1263namespace detail
1264{
1265
1266namespace det2
1267{
1268
1269using std::swap;
1270
1271template<class T> using is_swappable_impl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
1272
1273#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
1274
1275template<class T> struct is_nothrow_swappable_impl_
1276{
1277 static constexpr bool value = noexcept(swap(std::declval<T&>(), std::declval<T&>()));
1278};
1279
1280template<class T> using is_nothrow_swappable_impl = mp11::mp_bool< is_nothrow_swappable_impl_<T>::value >;
1281
1282#else
1283
1284template<class T> using is_nothrow_swappable_impl = typename std::enable_if<noexcept(swap(std::declval<T&>(), std::declval<T&>()))>::type;
1285
1286#endif
1287
1288} // namespace det2
1289
1290template<class T> struct is_swappable: mp11::mp_valid<det2::is_swappable_impl, T>
1291{
1292};
1293
1294#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
1295
1296template<class T> struct is_nothrow_swappable: mp11::mp_eval_if<mp11::mp_not<is_swappable<T>>, mp11::mp_false, det2::is_nothrow_swappable_impl, T>
1297{
1298};
1299
1300#else
1301
1302template<class T> struct is_nothrow_swappable: mp11::mp_valid<det2::is_nothrow_swappable_impl, T>
1303{
1304};
1305
1306#endif
1307
1308// variant_cc_base
1309
1310template<bool CopyConstructible, bool TriviallyCopyConstructible, class... T> struct variant_cc_base_impl;
1311
1312template<class... T> using variant_cc_base = variant_cc_base_impl<
1313 mp11::mp_all<std::is_copy_constructible<T>...>::value,
1314 mp11::mp_all<detail::is_trivially_copy_constructible<T>...>::value,
1315 T...>;
1316
1317template<class... T> struct variant_cc_base_impl<true, true, T...>: public variant_base<T...>
1318{
1319 using variant_base = detail::variant_base<T...>;
1320 using variant_base::variant_base;
1321
1322 variant_cc_base_impl() = default;
1323 variant_cc_base_impl( variant_cc_base_impl const& ) = default;
1324 variant_cc_base_impl( variant_cc_base_impl && ) = default;
1325 variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
1326 variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1327};
1328
1329template<bool B, class... T> struct variant_cc_base_impl<false, B, T...>: public variant_base<T...>
1330{
1331 using variant_base = detail::variant_base<T...>;
1332 using variant_base::variant_base;
1333
1334 variant_cc_base_impl() = default;
1335 variant_cc_base_impl( variant_cc_base_impl const& ) = delete;
1336 variant_cc_base_impl( variant_cc_base_impl && ) = default;
1337 variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
1338 variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1339};
1340
1341template<class... T> struct variant_cc_base_impl<true, false, T...>: public variant_base<T...>
1342{
1343 using variant_base = detail::variant_base<T...>;
1344 using variant_base::variant_base;
1345
1346public:
1347
1348 // constructors
1349
1350 variant_cc_base_impl() = default;
1351
1352 // copy constructor
1353
1354private:
1355
1356 struct L1
1357 {
1358 variant_base * this_;
1359 variant_base const & r;
1360
1361 template<class I> void operator()( I i ) const
1362 {
1363 this_->_replace( i, r._get_impl( i ) );
1364 }
1365 };
1366
1367public:
1368
1369 variant_cc_base_impl( variant_cc_base_impl const& r )
1370 noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
1371 : variant_base()
1372 {
1373 mp11::mp_with_index<sizeof...(T)>( r.index(), L1{ this, r } );
1374 }
1375
1376 // move constructor
1377
1378 variant_cc_base_impl( variant_cc_base_impl && ) = default;
1379
1380 // assignment
1381
1382 variant_cc_base_impl& operator=( variant_cc_base_impl const & ) = default;
1383 variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1384};
1385
1386// variant_ca_base
1387
1388template<bool CopyAssignable, bool TriviallyCopyAssignable, class... T> struct variant_ca_base_impl;
1389
1390template<class... T> using variant_ca_base = variant_ca_base_impl<
1391 mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>::value,
1392 mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>::value,
1393 T...>;
1394
1395template<class... T> struct variant_ca_base_impl<true, true, T...>: public variant_cc_base<T...>
1396{
1397 using variant_base = detail::variant_cc_base<T...>;
1398 using variant_base::variant_base;
1399
1400 variant_ca_base_impl() = default;
1401 variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1402 variant_ca_base_impl( variant_ca_base_impl && ) = default;
1403 variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = default;
1404 variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1405};
1406
1407template<bool B, class... T> struct variant_ca_base_impl<false, B, T...>: public variant_cc_base<T...>
1408{
1409 using variant_base = detail::variant_cc_base<T...>;
1410 using variant_base::variant_base;
1411
1412 variant_ca_base_impl() = default;
1413 variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1414 variant_ca_base_impl( variant_ca_base_impl && ) = default;
1415 variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = delete;
1416 variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1417};
1418
1419template<class... T> struct variant_ca_base_impl<true, false, T...>: public variant_cc_base<T...>
1420{
1421 using variant_base = detail::variant_cc_base<T...>;
1422 using variant_base::variant_base;
1423
1424public:
1425
1426 // constructors
1427
1428 variant_ca_base_impl() = default;
1429 variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1430 variant_ca_base_impl( variant_ca_base_impl && ) = default;
1431
1432 // copy assignment
1433
1434private:
1435
1436 struct L3
1437 {
1438 variant_base * this_;
1439 variant_base const & r;
1440
1441 template<class I> void operator()( I i ) const
1442 {
1443 this_->template emplace<I::value>( r._get_impl( i ) );
1444 }
1445 };
1446
1447public:
1448
1449 BOOST_CXX14_CONSTEXPR variant_ca_base_impl& operator=( variant_ca_base_impl const & r )
1450 noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
1451 {
1452 mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
1453 return *this;
1454 }
1455
1456 // move assignment
1457
1458 variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1459};
1460
1461// variant_mc_base
1462
1463template<bool MoveConstructible, bool TriviallyMoveConstructible, class... T> struct variant_mc_base_impl;
1464
1465template<class... T> using variant_mc_base = variant_mc_base_impl<
1466 mp11::mp_all<std::is_move_constructible<T>...>::value,
1467 mp11::mp_all<detail::is_trivially_move_constructible<T>...>::value,
1468 T...>;
1469
1470template<class... T> struct variant_mc_base_impl<true, true, T...>: public variant_ca_base<T...>
1471{
1472 using variant_base = detail::variant_ca_base<T...>;
1473 using variant_base::variant_base;
1474
1475 variant_mc_base_impl() = default;
1476 variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1477 variant_mc_base_impl( variant_mc_base_impl && ) = default;
1478 variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
1479 variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1480};
1481
1482template<bool B, class... T> struct variant_mc_base_impl<false, B, T...>: public variant_ca_base<T...>
1483{
1484 using variant_base = detail::variant_ca_base<T...>;
1485 using variant_base::variant_base;
1486
1487 variant_mc_base_impl() = default;
1488 variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1489 variant_mc_base_impl( variant_mc_base_impl && ) = delete;
1490 variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
1491 variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1492};
1493
1494template<class... T> struct variant_mc_base_impl<true, false, T...>: public variant_ca_base<T...>
1495{
1496 using variant_base = detail::variant_ca_base<T...>;
1497 using variant_base::variant_base;
1498
1499public:
1500
1501 // constructors
1502
1503 variant_mc_base_impl() = default;
1504 variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1505
1506 // move constructor
1507
1508private:
1509
1510 struct L2
1511 {
1512 variant_base * this_;
1513 variant_base & r;
1514
1515 template<class I> void operator()( I i ) const
1516 {
1517 this_->_replace( i, std::move( r._get_impl( i ) ) );
1518 }
1519 };
1520
1521public:
1522
1523 variant_mc_base_impl( variant_mc_base_impl && r )
1524 noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
1525 {
1526 mp11::mp_with_index<sizeof...(T)>( r.index(), L2{ this, r } );
1527 }
1528
1529 // assignment
1530
1531 variant_mc_base_impl& operator=( variant_mc_base_impl const & ) = default;
1532 variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1533};
1534
1535// variant_ma_base
1536
1537template<bool MoveAssignable, bool TriviallyMoveAssignable, class... T> struct variant_ma_base_impl;
1538
1539template<class... T> using variant_ma_base = variant_ma_base_impl<
1540 mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>::value,
1541 mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>::value,
1542 T...>;
1543
1544template<class... T> struct variant_ma_base_impl<true, true, T...>: public variant_mc_base<T...>
1545{
1546 using variant_base = detail::variant_mc_base<T...>;
1547 using variant_base::variant_base;
1548
1549 variant_ma_base_impl() = default;
1550 variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1551 variant_ma_base_impl( variant_ma_base_impl && ) = default;
1552 variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
1553 variant_ma_base_impl& operator=( variant_ma_base_impl && ) = default;
1554};
1555
1556template<bool B, class... T> struct variant_ma_base_impl<false, B, T...>: public variant_mc_base<T...>
1557{
1558 using variant_base = detail::variant_mc_base<T...>;
1559 using variant_base::variant_base;
1560
1561 variant_ma_base_impl() = default;
1562 variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1563 variant_ma_base_impl( variant_ma_base_impl && ) = default;
1564 variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
1565 variant_ma_base_impl& operator=( variant_ma_base_impl && ) = delete;
1566};
1567
1568template<class... T> struct variant_ma_base_impl<true, false, T...>: public variant_mc_base<T...>
1569{
1570 using variant_base = detail::variant_mc_base<T...>;
1571 using variant_base::variant_base;
1572
1573public:
1574
1575 // constructors
1576
1577 variant_ma_base_impl() = default;
1578 variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1579 variant_ma_base_impl( variant_ma_base_impl && ) = default;
1580
1581 // copy assignment
1582
1583 variant_ma_base_impl& operator=( variant_ma_base_impl const & ) = default;
1584
1585 // move assignment
1586
1587private:
1588
1589 struct L4
1590 {
1591 variant_base * this_;
1592 variant_base & r;
1593
1594 template<class I> void operator()( I i ) const
1595 {
1596 this_->template emplace<I::value>( std::move( r._get_impl( i ) ) );
1597 }
1598 };
1599
1600public:
1601
1602 variant_ma_base_impl& operator=( variant_ma_base_impl && r )
1603 noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
1604 {
1605 mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
1606 return *this;
1607 }
1608};
1609
1610} // namespace detail
1611
1612// variant
1613
1614template<class... T> class variant: private detail::variant_ma_base<T...>
1615{
1616private:
1617
1618 using variant_base = detail::variant_ma_base<T...>;
1619
1620public:
1621
1622 // constructors
1623
1624 template<class E1 = void, class E2 = mp11::mp_if<std::is_default_constructible< mp11::mp_first<variant<T...>> >, E1>>
1625 constexpr variant()
1626 noexcept( std::is_nothrow_default_constructible< mp11::mp_first<variant<T...>> >::value )
1627 : variant_base( mp11::mp_size_t<0>() )
1628 {
1629 }
1630
1631 // variant( variant const& ) = default;
1632 // variant( variant && ) = default;
1633
1634 template<class U,
1635 class Ud = typename std::decay<U>::type,
1636 class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !std::is_base_of<variant, Ud>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
1637
1638#if BOOST_WORKAROUND(BOOST_MSVC, < 1940)
1639
1640 class V = mp11::mp_apply_q< mp11::mp_bind_front<detail::resolve_overload_type, U&&>, variant >,
1641
1642#else
1643
1644 class V = detail::resolve_overload_type<U&&, T...>,
1645
1646#endif
1647
1648 class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type
1649 >
1650 constexpr variant( U&& u )
1651 noexcept( std::is_nothrow_constructible<V, U&&>::value )
1652 : variant_base( detail::resolve_overload_index<U&&, T...>(), std::forward<U>(u) )
1653 {
1654 }
1655
1656 template<class U, class... A, class I = mp11::mp_find<variant<T...>, U>, class E = typename std::enable_if<std::is_constructible<U, A&&...>::value>::type>
1657 constexpr explicit variant( in_place_type_t<U>, A&&... a ): variant_base( I(), std::forward<A>(a)... )
1658 {
1659 }
1660
1661 template<class U, class V, class... A, class I = mp11::mp_find<variant<T...>, U>, class E = typename std::enable_if<std::is_constructible<U, std::initializer_list<V>&, A&&...>::value>::type>
1662 constexpr explicit variant( in_place_type_t<U>, std::initializer_list<V> il, A&&... a ): variant_base( I(), il, std::forward<A>(a)... )
1663 {
1664 }
1665
1666 template<std::size_t I, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, A&&...>::value>::type>
1667 constexpr explicit variant( in_place_index_t<I>, A&&... a ): variant_base( mp11::mp_size_t<I>(), std::forward<A>(a)... )
1668 {
1669 }
1670
1671 template<std::size_t I, class V, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, std::initializer_list<V>&, A&&...>::value>::type>
1672 constexpr explicit variant( in_place_index_t<I>, std::initializer_list<V> il, A&&... a ): variant_base( mp11::mp_size_t<I>(), il, std::forward<A>(a)... )
1673 {
1674 }
1675
1676 // assignment
1677
1678 // variant& operator=( variant const& ) = default;
1679 // variant& operator=( variant && ) = default;
1680
1681 template<class U,
1682 class E1 = typename std::enable_if<!std::is_same<typename std::decay<U>::type, variant>::value>::type,
1683 class V = detail::resolve_overload_type<U, T...>,
1684 class E2 = typename std::enable_if<std::is_assignable<V&, U&&>::value && std::is_constructible<V, U&&>::value>::type
1685 >
1686 BOOST_CXX14_CONSTEXPR variant& operator=( U&& u )
1687 noexcept( std::is_nothrow_constructible<V, U&&>::value )
1688 {
1689 std::size_t const I = detail::resolve_overload_index<U, T...>::value;
1690 this->template emplace<I>( std::forward<U>(u) );
1691 return *this;
1692 }
1693
1694 // modifiers
1695
1696 template<class U, class... A,
1697 class E = typename std::enable_if< mp11::mp_count<variant<T...>, U>::value == 1 && std::is_constructible<U, A&&...>::value >::type>
1698 BOOST_CXX14_CONSTEXPR U& emplace( A&&... a )
1699 {
1700 using I = mp11::mp_find<variant<T...>, U>;
1701 variant_base::template emplace<I::value>( std::forward<A>(a)... );
1702 return _get_impl( I() );
1703 }
1704
1705 template<class U, class V, class... A,
1706 class E = typename std::enable_if< mp11::mp_count<variant<T...>, U>::value == 1 && std::is_constructible<U, std::initializer_list<V>&, A&&...>::value >::type>
1707 BOOST_CXX14_CONSTEXPR U& emplace( std::initializer_list<V> il, A&&... a )
1708 {
1709 using I = mp11::mp_find<variant<T...>, U>;
1710 variant_base::template emplace<I::value>( il, std::forward<A>(a)... );
1711 return _get_impl( I() );
1712 }
1713
1714 template<std::size_t I, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, A&&...>::value>::type>
1715 BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( A&&... a )
1716 {
1717 variant_base::template emplace<I>( std::forward<A>(a)... );
1718 return _get_impl( mp11::mp_size_t<I>() );
1719 }
1720
1721 template<std::size_t I, class V, class... A, class E = typename std::enable_if<std::is_constructible<mp11::mp_at_c<variant<T...>, I>, std::initializer_list<V>&, A&&...>::value>::type>
1722 BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( std::initializer_list<V> il, A&&... a )
1723 {
1724 variant_base::template emplace<I>( il, std::forward<A>(a)... );
1725 return _get_impl( mp11::mp_size_t<I>() );
1726 }
1727
1728 // value status
1729
1730 constexpr bool valueless_by_exception() const noexcept
1731 {
1732 return false;
1733 }
1734
1735 using variant_base::index;
1736
1737 using variant_base::uses_double_storage;
1738
1739 // swap
1740
1741private:
1742
1743 struct L5
1744 {
1745 variant * this_;
1746 variant & r;
1747
1748 template<class I> void operator()( I i ) const
1749 {
1750 using std::swap;
1751 swap( this_->_get_impl( i ), r._get_impl( i ) );
1752 }
1753 };
1754
1755public:
1756
1757 void swap( variant& r ) noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>..., detail::is_nothrow_swappable<T>...>::value )
1758 {
1759 if( index() == r.index() )
1760 {
1761 mp11::mp_with_index<sizeof...(T)>( index(), L5{ this, r } );
1762 }
1763 else
1764 {
1765 variant tmp( std::move(*this) );
1766 *this = std::move( r );
1767 r = std::move( tmp );
1768 }
1769 }
1770
1771 // private accessors
1772
1773 using variant_base::_get_impl;
1774
1775 // converting constructors (extension)
1776
1777private:
1778
1779 template<class... U> struct L6
1780 {
1781 variant_base * this_;
1782 variant<U...> const & r;
1783
1784 template<class I> void operator()( I i ) const
1785 {
1786 using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
1787 this_->_replace( J{}, r._get_impl( i ) );
1788 }
1789 };
1790
1791public:
1792
1793 template<class... U,
1794 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1795 variant( variant<U...> const& r )
1796 noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<U>...>::value )
1797 {
1798 mp11::mp_with_index<sizeof...(U)>( r.index(), L6<U...>{ this, r } );
1799 }
1800
1801private:
1802
1803 template<class... U> struct L7
1804 {
1805 variant_base * this_;
1806 variant<U...> & r;
1807
1808 template<class I> void operator()( I i ) const
1809 {
1810 using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
1811 this_->_replace( J{}, std::move( r._get_impl( i ) ) );
1812 }
1813 };
1814
1815public:
1816
1817 template<class... U,
1818 class E2 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1819 variant( variant<U...> && r )
1820 noexcept( mp11::mp_all<std::is_nothrow_move_constructible<U>...>::value )
1821 {
1822 mp11::mp_with_index<sizeof...(U)>( r.index(), L7<U...>{ this, r } );
1823 }
1824
1825 // subset (extension)
1826
1827private:
1828
1829 template<class... U, class V, std::size_t J, class E = typename std::enable_if<J != sizeof...(U)>::type> static constexpr variant<U...> _subset_impl( mp11::mp_size_t<J>, V && v )
1830 {
1831 return variant<U...>( in_place_index_t<J>(), std::forward<V>(v) );
1832 }
1833
1834 template<class... U, class V> static variant<U...> _subset_impl( mp11::mp_size_t<sizeof...(U)>, V && /*v*/ )
1835 {
1836 detail::throw_bad_variant_access();
1837 }
1838
1839private:
1840
1841 template<class... U> struct L8
1842 {
1843 variant * this_;
1844
1845 template<class I> variant<U...> operator()( I i ) const
1846 {
1847 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1848 return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
1849 }
1850 };
1851
1852public:
1853
1854 template<class... U,
1855 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1856 BOOST_CXX14_CONSTEXPR variant<U...> subset() &
1857 {
1858 return mp11::mp_with_index<sizeof...(T)>( index(), L8<U...>{ this } );
1859 }
1860
1861private:
1862
1863 template<class... U> struct L9
1864 {
1865 variant const * this_;
1866
1867 template<class I> variant<U...> operator()( I i ) const
1868 {
1869 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1870 return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
1871 }
1872 };
1873
1874public:
1875
1876 template<class... U,
1877 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1878 constexpr variant<U...> subset() const&
1879 {
1880 return mp11::mp_with_index<sizeof...(T)>( index(), L9<U...>{ this } );
1881 }
1882
1883private:
1884
1885 template<class... U> struct L10
1886 {
1887 variant * this_;
1888
1889 template<class I> variant<U...> operator()( I i ) const
1890 {
1891 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1892 return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
1893 }
1894 };
1895
1896public:
1897
1898 template<class... U,
1899 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1900 BOOST_CXX14_CONSTEXPR variant<U...> subset() &&
1901 {
1902 return mp11::mp_with_index<sizeof...(T)>( index(), L10<U...>{ this } );
1903 }
1904
1905#if !BOOST_WORKAROUND(BOOST_GCC, < 40900)
1906
1907 // g++ 4.8 doesn't handle const&& particularly well
1908
1909private:
1910
1911 template<class... U> struct L11
1912 {
1913 variant const * this_;
1914
1915 template<class I> variant<U...> operator()( I i ) const
1916 {
1917 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1918 return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
1919 }
1920 };
1921
1922public:
1923
1924 template<class... U,
1925 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1926 constexpr variant<U...> subset() const&&
1927 {
1928 return mp11::mp_with_index<sizeof...(T)>( index(), L11<U...>{ this } );
1929 }
1930
1931#endif
1932};
1933
1934// relational operators
1935
1936namespace detail
1937{
1938
1939template<class... T> struct eq_L
1940{
1941 variant<T...> const & v;
1942 variant<T...> const & w;
1943
1944 template<class I> constexpr bool operator()( I i ) const
1945 {
1946 return v._get_impl( i ) == w._get_impl( i );
1947 }
1948};
1949
1950} // namespace detail
1951
1952template<class... T> constexpr bool operator==( variant<T...> const & v, variant<T...> const & w )
1953{
1954 return v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::eq_L<T...>{ v, w } );
1955}
1956
1957namespace detail
1958{
1959
1960template<class... T> struct ne_L
1961{
1962 variant<T...> const & v;
1963 variant<T...> const & w;
1964
1965 template<class I> constexpr bool operator()( I i ) const
1966 {
1967 return v._get_impl( i ) != w._get_impl( i );
1968 }
1969};
1970
1971} // namespace detail
1972
1973template<class... T> constexpr bool operator!=( variant<T...> const & v, variant<T...> const & w )
1974{
1975 return v.index() != w.index() || mp11::mp_with_index<sizeof...(T)>( v.index(), detail::ne_L<T...>{ v, w } );
1976}
1977
1978namespace detail
1979{
1980
1981template<class... T> struct lt_L
1982{
1983 variant<T...> const & v;
1984 variant<T...> const & w;
1985
1986 template<class I> constexpr bool operator()( I i ) const
1987 {
1988 return v._get_impl( i ) < w._get_impl( i );
1989 }
1990};
1991
1992} // namespace detail
1993
1994template<class... T> constexpr bool operator<( variant<T...> const & v, variant<T...> const & w )
1995{
1996 return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::lt_L<T...>{ v, w } ) );
1997}
1998
1999template<class... T> constexpr bool operator>( variant<T...> const & v, variant<T...> const & w )
2000{
2001 return w < v;
2002}
2003
2004namespace detail
2005{
2006
2007template<class... T> struct le_L
2008{
2009 variant<T...> const & v;
2010 variant<T...> const & w;
2011
2012 template<class I> constexpr bool operator()( I i ) const
2013 {
2014 return v._get_impl( i ) <= w._get_impl( i );
2015 }
2016};
2017
2018} // namespace detail
2019
2020template<class... T> constexpr bool operator<=( variant<T...> const & v, variant<T...> const & w )
2021{
2022 return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::le_L<T...>{ v, w } ) );
2023}
2024
2025template<class... T> constexpr bool operator>=( variant<T...> const & v, variant<T...> const & w )
2026{
2027 return w <= v;
2028}
2029
2030// visitation
2031namespace detail
2032{
2033
2034template<class T> using remove_cv_ref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
2035
2036template<class... T> variant<T...> const & extract_variant_base_( variant<T...> const & );
2037
2038#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
2039
2040template<class V> struct extract_vbase_impl
2041{
2042 using type = decltype( extract_variant_base_( std::declval<V>() ) );
2043};
2044
2045template<class V> using extract_variant_base = remove_cv_ref_t< typename extract_vbase_impl<V>::type >;
2046
2047#else
2048
2049template<class V> using extract_variant_base = remove_cv_ref_t< decltype( extract_variant_base_( std::declval<V>() ) ) >;
2050
2051#endif
2052
2053template<class V> using variant_base_size = variant_size< extract_variant_base<V> >;
2054
2055template<class T, class U> struct copy_cv_ref
2056{
2057 using type = T;
2058};
2059
2060template<class T, class U> struct copy_cv_ref<T, U const>
2061{
2062 using type = T const;
2063};
2064
2065template<class T, class U> struct copy_cv_ref<T, U volatile>
2066{
2067 using type = T volatile;
2068};
2069
2070template<class T, class U> struct copy_cv_ref<T, U const volatile>
2071{
2072 using type = T const volatile;
2073};
2074
2075template<class T, class U> struct copy_cv_ref<T, U&>
2076{
2077 using type = typename copy_cv_ref<T, U>::type&;
2078};
2079
2080template<class T, class U> struct copy_cv_ref<T, U&&>
2081{
2082 using type = typename copy_cv_ref<T, U>::type&&;
2083};
2084
2085template<class T, class U> using copy_cv_ref_t = typename copy_cv_ref<T, U>::type;
2086
2087template<class F> struct Qret
2088{
2089 template<class... T> using fn = decltype( std::declval<F>()( std::declval<T>()... ) );
2090};
2091
2092template<class L> using front_if_same = mp11::mp_if<mp11::mp_apply<mp11::mp_same, L>, mp11::mp_front<L>>;
2093
2094template<class V> using apply_cv_ref = mp11::mp_product<copy_cv_ref_t, extract_variant_base<V>, mp11::mp_list<V>>;
2095
2096struct deduced {};
2097
2098#if !BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
2099
2100template<class R, class F, class... V> using Vret = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...> >;
2101
2102#else
2103
2104template<class R, class F, class... V> struct Vret_impl
2105{
2106 using type = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...> >;
2107};
2108
2109template<class R, class F, class... V> using Vret = typename Vret_impl<R, F, V...>::type;
2110
2111#endif
2112
2113} // namespace detail
2114
2115template<class R = detail::deduced, class F> constexpr auto visit( F&& f ) -> detail::Vret<R, F>
2116{
2117 return std::forward<F>(f)();
2118}
2119
2120namespace detail
2121{
2122
2123template<class R, class F, class V1> struct visit_L1
2124{
2125 F&& f;
2126 V1&& v1;
2127
2128 template<class I> auto operator()( I ) const -> Vret<R, F, V1>
2129 {
2130 return std::forward<F>(f)( unsafe_get<I::value>( std::forward<V1>(v1) ) );
2131 }
2132};
2133
2134} // namespace detail
2135
2136template<class R = detail::deduced, class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<R, F, V1>
2137{
2138 return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L1<R, F, V1>{ std::forward<F>(f), std::forward<V1>(v1) } );
2139}
2140
2141#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) || BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
2142
2143namespace detail
2144{
2145
2146template<class F, class A> struct bind_front_
2147{
2148 F&& f;
2149 A&& a;
2150
2151 template<class... T> auto operator()( T&&... t ) -> decltype( std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... ) )
2152 {
2153 return std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... );
2154 }
2155};
2156
2157template<class F, class A> bind_front_<F, A> bind_front( F&& f, A&& a )
2158{
2159 return bind_front_<F, A>{ std::forward<F>(f), std::forward<A>(a) };
2160}
2161
2162template<class R, class F, class V1, class V2> struct visit_L2
2163{
2164 F&& f;
2165
2166 V1&& v1;
2167 V2&& v2;
2168
2169 template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2>
2170 {
2171 auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2172 return visit<R>( f2, std::forward<V2>(v2) );
2173 }
2174};
2175
2176} // namespace detail
2177
2178template<class R = detail::deduced, class F, class V1, class V2> constexpr auto visit( F&& f, V1&& v1, V2&& v2 ) -> detail::Vret<R, F, V1, V2>
2179{
2180 return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L2<R, F, V1, V2>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2) } );
2181}
2182
2183namespace detail
2184{
2185
2186template<class R, class F, class V1, class V2, class V3> struct visit_L3
2187{
2188 F&& f;
2189
2190 V1&& v1;
2191 V2&& v2;
2192 V3&& v3;
2193
2194 template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3>
2195 {
2196 auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2197 return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
2198 }
2199};
2200
2201} // namespace detail
2202
2203template<class R = detail::deduced, class F, class V1, class V2, class V3> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3 ) -> detail::Vret<R, F, V1, V2, V3>
2204{
2205 return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L3<R, F, V1, V2, V3>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3) } );
2206}
2207
2208namespace detail
2209{
2210
2211template<class R, class F, class V1, class V2, class V3, class V4> struct visit_L4
2212{
2213 F&& f;
2214
2215 V1&& v1;
2216 V2&& v2;
2217 V3&& v3;
2218 V4&& v4;
2219
2220 template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3, V4>
2221 {
2222 auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2223 return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
2224 }
2225};
2226
2227} // namespace detail
2228
2229template<class R = detail::deduced, class F, class V1, class V2, class V3, class V4> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3, V4&& v4 ) -> detail::Vret<R, F, V1, V2, V3, V4>
2230{
2231 return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L4<R, F, V1, V2, V3, V4>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) } );
2232}
2233
2234#else
2235
2236template<class R = detail::deduced, class F, class V1, class V2, class... V> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V&&... v ) -> detail::Vret<R, F, V1, V2, V...>
2237{
2238 return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), [&]( auto I ){
2239
2240 auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
2241 return visit<R>( f2, std::forward<V2>(v2), std::forward<V>(v)... );
2242
2243 });
2244}
2245
2246#endif
2247
2248// specialized algorithms
2249template<class... T,
2250 class E = typename std::enable_if<mp11::mp_all<std::is_move_constructible<T>..., detail::is_swappable<T>...>::value>::type>
2251void swap( variant<T...> & v, variant<T...> & w )
2252 noexcept( noexcept(v.swap(w)) )
2253{
2254 v.swap( w );
2255}
2256
2257// visit_by_index
2258
2259namespace detail
2260{
2261
2262template<class R, class V, class... F> using Vret2 = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_transform<mp11::mp_invoke_q, mp11::mp_list<Qret<F>...>, apply_cv_ref<V>> >;
2263
2264template<class R, class V, class... F> struct visit_by_index_L
2265{
2266 V&& v;
2267 std::tuple<F&&...> tp;
2268
2269 template<class I> constexpr detail::Vret2<R, V, F...> operator()( I ) const
2270 {
2271 return std::get<I::value>( std::move(tp) )( unsafe_get<I::value>( std::forward<V>(v) ) );
2272 }
2273};
2274
2275} // namespace detail
2276
2277template<class R = detail::deduced, class V, class... F> constexpr auto visit_by_index( V&& v, F&&... f ) -> detail::Vret2<R, V, F...>
2278{
2279 static_assert( variant_size<V>::value == sizeof...(F), "Incorrect number of function objects" );
2280
2281 return mp11::mp_with_index<variant_size<V>::value>( v.index(),
2282 detail::visit_by_index_L<R, V, F...>{ std::forward<V>(v), std::tuple<F&&...>( std::forward<F>(f)... ) } );
2283}
2284
2285// output streaming
2286
2287namespace detail
2288{
2289
2290template<class Ch, class Tr, class... T> struct ostream_insert_L
2291{
2292 std::basic_ostream<Ch, Tr>& os;
2293 variant<T...> const& v;
2294
2295 template<class I> std::basic_ostream<Ch, Tr>& operator()( I ) const
2296 {
2297 return os << unsafe_get<I::value>( v );
2298 }
2299};
2300
2301template<class Os, class T, class E = void> struct is_output_streamable: std::false_type
2302{
2303};
2304
2305template<class Os, class T> struct is_output_streamable<Os, T, decltype( std::declval<Os&>() << std::declval<T const&>(), (void)0 )>: std::true_type
2306{
2307};
2308
2309} // namespace detail
2310
2311template<class Ch, class Tr>
2312std::basic_ostream<Ch, Tr>& operator<<( std::basic_ostream<Ch, Tr>& os, monostate const& )
2313{
2314 os << "monostate";
2315 return os;
2316}
2317
2318template<class Ch, class Tr, class T1, class... T,
2319 class E = typename std::enable_if< mp11::mp_all< detail::is_output_streamable<std::basic_ostream<Ch, Tr>, T>... >::value >::type >
2320std::basic_ostream<Ch, Tr>& operator<<( std::basic_ostream<Ch, Tr>& os, variant<T1, T...> const& v )
2321{
2322 return mp11::mp_with_index<1 + sizeof...(T)>( v.index(),
2323 detail::ostream_insert_L<Ch, Tr, T1, T...>{ os, v } );
2324}
2325
2326// hashing support
2327
2328namespace detail
2329{
2330
2331inline std::size_t hash_value_impl_( mp11::mp_true, std::size_t index, std::size_t value )
2332{
2333 unsigned long long hv = 0xCBF29CE484222325ull;
2334 unsigned long long const prime = 0x100000001B3ull;
2335
2336 hv ^= index;
2337 hv *= prime;
2338
2339 hv ^= value;
2340 hv *= prime;
2341
2342 return static_cast<std::size_t>( hv );
2343}
2344
2345inline std::size_t hash_value_impl_( mp11::mp_false, std::size_t index, std::size_t value )
2346{
2347 std::size_t hv = 0x811C9DC5;
2348 std::size_t const prime = 0x01000193;
2349
2350 hv ^= index;
2351 hv *= prime;
2352
2353 hv ^= value;
2354 hv *= prime;
2355
2356 return hv;
2357}
2358
2359inline std::size_t hash_value_impl( std::size_t index, std::size_t value )
2360{
2361 return hash_value_impl_( mp11::mp_bool< (SIZE_MAX > UINT32_MAX) >(), index, value );
2362}
2363
2364template<template<class> class H, class V> struct hash_value_L
2365{
2366 V const & v;
2367
2368 template<class I> std::size_t operator()( I ) const
2369 {
2370 auto const & t = unsafe_get<I::value>( v );
2371
2372 std::size_t index = I::value;
2373 std::size_t value = H<remove_cv_ref_t<decltype(t)>>()( t );
2374
2375 return hash_value_impl( index, value );
2376 }
2377};
2378
2379template<class... T> std::size_t hash_value_std( variant<T...> const & v )
2380{
2381 return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< std::hash, variant<T...> >{ v } );
2382}
2383
2384} // namespace detail
2385
2386inline std::size_t hash_value( monostate const & )
2387{
2388 return 0xA7EE4757u;
2389}
2390
2391template<class... T> std::size_t hash_value( variant<T...> const & v )
2392{
2393 return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< boost::hash, variant<T...> >{ v } );
2394}
2395
2396namespace detail
2397{
2398
2399template<class T> using is_hash_enabled = std::is_default_constructible< std::hash<typename std::remove_const<T>::type> >;
2400
2401template<class V, bool E = mp11::mp_all_of<V, is_hash_enabled>::value> struct std_hash_impl;
2402
2403template<class V> struct std_hash_impl<V, false>
2404{
2405 std_hash_impl() = delete;
2406 std_hash_impl( std_hash_impl const& ) = delete;
2407 std_hash_impl& operator=( std_hash_impl const& ) = delete;
2408};
2409
2410template<class V> struct std_hash_impl<V, true>
2411{
2412 std::size_t operator()( V const & v ) const
2413 {
2414 return detail::hash_value_std( v );
2415 }
2416};
2417
2418} // namespace detail
2419
2420} // namespace variant2
2421} // namespace boost
2422
2423namespace std
2424{
2425
2426template<class... T> struct hash< ::boost::variant2::variant<T...> >: public ::boost::variant2::detail::std_hash_impl< ::boost::variant2::variant<T...> >
2427{
2428};
2429
2430template<> struct hash< ::boost::variant2::monostate >
2431{
2432 std::size_t operator()( ::boost::variant2::monostate const & v ) const
2433 {
2434 return hash_value( v );
2435 }
2436};
2437
2438} // namespace std
2439
2440// JSON support
2441
2442namespace boost
2443{
2444namespace json
2445{
2446
2447class value;
2448
2449struct value_from_tag;
2450
2451template<class T>
2452void value_from( T&& t, value& jv );
2453
2454template<class T>
2455struct try_value_to_tag;
2456
2457template<class T1, class T2>
2458struct result_for;
2459
2460template<class T>
2461typename result_for<T, value>::type
2462try_value_to( value const & jv );
2463
2464template<class T>
2465typename result_for<T, value>::type
2466result_from_errno( int e, boost::source_location const* loc ) noexcept;
2467
2468template<class T> struct is_null_like;
2469
2470template<> struct is_null_like<variant2::monostate>: std::true_type {};
2471
2472} // namespace json
2473
2474namespace variant2
2475{
2476
2477namespace detail
2478{
2479
2480struct tag_invoke_L1
2481{
2482 boost::json::value& v;
2483
2484#if defined(BOOST_MSVC) && BOOST_MSVC / 10 == 191
2485 // msvc-14.1 with /permissive- needs this
2486 explicit tag_invoke_L1( boost::json::value& v_ ): v( v_ ) {}
2487#endif
2488
2489 template<class T> void operator()( T const& t ) const
2490 {
2491 boost::json::value_from( t, v );
2492 }
2493};
2494
2495} // namespace detail
2496
2497template<class... T>
2498 void tag_invoke( boost::json::value_from_tag const&, boost::json::value& v, variant<T...> const & w )
2499{
2500 visit( detail::tag_invoke_L1{ .v: v }, w );
2501}
2502
2503namespace detail
2504{
2505
2506template<class V> struct tag_invoke_L2
2507{
2508 boost::json::value const& v;
2509 typename boost::json::result_for<V, boost::json::value>::type& r;
2510
2511 template<class I> void operator()( I /*i*/ ) const
2512 {
2513 if( !r )
2514 {
2515 using Ti = mp11::mp_at_c<V, I::value>;
2516 auto r2 = boost::json::try_value_to<Ti>( v );
2517
2518 if( r2 )
2519 {
2520 r.emplace( in_place_index_t<I::value>{}, std::move( *r2 ) );
2521 }
2522 }
2523 }
2524};
2525
2526} // namespace detail
2527
2528template<class... T>
2529 typename boost::json::result_for<variant<T...>, boost::json::value>::type
2530 tag_invoke( boost::json::try_value_to_tag<variant<T...>> const&, boost::json::value const& v )
2531{
2532 static constexpr boost::source_location loc = BOOST_CURRENT_LOCATION;
2533 auto r = boost::json::result_from_errno< variant<T...> >( EINVAL, &loc );
2534
2535 mp11::mp_for_each<mp11::mp_iota_c<sizeof...(T)>>( detail::tag_invoke_L2< variant<T...> >{ v, r } );
2536
2537 return r;
2538}
2539
2540} // namespace variant2
2541} // namespace boost
2542
2543#undef BOOST_VARIANT2_CX14_ASSERT
2544
2545#if defined(_MSC_VER) && _MSC_VER < 1910
2546# pragma warning( pop )
2547#endif
2548
2549#endif // #ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
2550

source code of boost/libs/variant2/include/boost/variant2/variant.hpp