1 #ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
2 #define BOOST_VARIANT2_VARIANT_HPP_INCLUDED
4 // Copyright 2017-2019 Peter Dimov.
6 // Distributed under the Boost Software License, Version 1.0.
8 // See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt
11 #if defined(_MSC_VER) && _MSC_VER < 1910
12 # pragma warning( push )
13 # pragma warning( disable: 4521 4522 ) // multiple copy operators
16 #ifndef BOOST_MP11_HPP_INCLUDED
17 #include <boost/mp11.hpp>
19 #include <boost/config.hpp>
20 #include <boost/detail/workaround.hpp>
21 #include <boost/cstdint.hpp>
23 #include <type_traits>
26 #include <initializer_list>
28 #include <functional> // std::hash
35 #ifdef BOOST_NO_EXCEPTIONS
37 BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
46 class bad_variant_access: public std::exception
50 bad_variant_access() noexcept
54 char const * what() const noexcept
56 return "bad_variant_access";
63 BOOST_NORETURN inline void throw_bad_variant_access()
65 #ifdef BOOST_NO_EXCEPTIONS
67 boost::throw_exception( bad_variant_access() );
71 throw bad_variant_access();
84 constexpr bool operator<(monostate, monostate) noexcept { return false; }
85 constexpr bool operator>(monostate, monostate) noexcept { return false; }
86 constexpr bool operator<=(monostate, monostate) noexcept { return true; }
87 constexpr bool operator>=(monostate, monostate) noexcept { return true; }
88 constexpr bool operator==(monostate, monostate) noexcept { return true; }
89 constexpr bool operator!=(monostate, monostate) noexcept { return false; }
91 // variant forward declaration
93 template<class... T> class variant;
97 template<class T> struct variant_size
101 template<class T> struct variant_size<T const>: variant_size<T>
105 template<class T> struct variant_size<T volatile>: variant_size<T>
109 template<class T> struct variant_size<T const volatile>: variant_size<T>
113 template<class T> struct variant_size<T&>: variant_size<T>
117 template<class T> struct variant_size<T&&>: variant_size<T>
121 #if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
123 template <class T> /*inline*/ constexpr std::size_t variant_size_v = variant_size<T>::value;
127 template <class... T> struct variant_size<variant<T...>>: mp11::mp_size<variant<T...>>
131 // variant_alternative
133 template<std::size_t I, class T> struct variant_alternative;
135 template<std::size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type;
137 #if BOOST_WORKAROUND(BOOST_GCC, < 40900)
142 template<std::size_t I, class T, bool E> struct variant_alternative_impl
146 template<std::size_t I, class... T> struct variant_alternative_impl<I, variant<T...>, true>
148 using type = mp11::mp_at_c<variant<T...>, I>;
151 template<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> >
155 template<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> >
159 template<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> >
163 template<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> >
167 template<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 >
171 template<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 >
175 template<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 >
179 template<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> >
183 template<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 >
187 template<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 >
191 template<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 >
195 } // namespace detail
197 template<std::size_t I, class T> struct variant_alternative
201 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>: public detail::variant_alternative_impl<I, variant<T...>, (I < sizeof...(T))>
205 template<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))>
209 template<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))>
213 template<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))>
217 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&>: public detail::variant_alternative_impl<I, variant<T...>&, (I < sizeof...(T))>
221 template<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))>
225 template<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))>
229 template<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))>
233 template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>&&>: public detail::variant_alternative_impl<I, variant<T...>&&, (I < sizeof...(T))>
237 template<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))>
241 template<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))>
245 template<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))>
254 #if defined( BOOST_MP11_VERSION ) && BOOST_MP11_VERSION >= 107000
256 template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke_q<Q, variant_alternative_t<I::value, T>>;
260 template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke<Q, variant_alternative_t<I::value, T>>;
264 } // namespace detail
266 template<std::size_t I, class T> struct variant_alternative
270 template<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>>
274 template<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>>
278 template<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>>
282 template<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>>
286 template<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>>
290 template<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>>
298 constexpr std::size_t variant_npos = ~static_cast<std::size_t>( 0 );
302 template<class U, class... T> constexpr bool holds_alternative( variant<T...> const& v ) noexcept
304 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
305 return v.index() == mp11::mp_find<variant<T...>, U>::value;
310 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& get(variant<T...>& v)
312 static_assert( I < sizeof...(T), "Index out of bounds" );
313 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
316 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& get(variant<T...>&& v)
318 static_assert( I < sizeof...(T), "Index out of bounds" );
320 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
322 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
326 if( v.index() != I ) detail::throw_bad_variant_access();
327 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
332 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& get(variant<T...> const& v)
334 static_assert( I < sizeof...(T), "Index out of bounds" );
335 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( mp11::mp_size_t<I>() );
338 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& get(variant<T...> const&& v)
340 static_assert( I < sizeof...(T), "Index out of bounds" );
342 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
344 return ( v.index() != I? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( mp11::mp_size_t<I>() ) );
348 if( v.index() != I ) detail::throw_bad_variant_access();
349 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
354 // detail::unsafe_get (for visit)
359 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& unsafe_get(variant<T...>& v)
361 static_assert( I < sizeof...(T), "Index out of bounds" );
362 return v._get_impl( mp11::mp_size_t<I>() );
365 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& unsafe_get(variant<T...>&& v)
367 static_assert( I < sizeof...(T), "Index out of bounds" );
368 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
371 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& unsafe_get(variant<T...> const& v)
373 static_assert( I < sizeof...(T), "Index out of bounds" );
374 return v._get_impl( mp11::mp_size_t<I>() );
377 template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& unsafe_get(variant<T...> const&& v)
379 static_assert( I < sizeof...(T), "Index out of bounds" );
380 return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
383 } // namespace detail
387 template<class U, class... T> constexpr U& get(variant<T...>& v)
389 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
391 using I = mp11::mp_find<variant<T...>, U>;
393 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
396 template<class U, class... T> constexpr U&& get(variant<T...>&& v)
398 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
400 using I = mp11::mp_find<variant<T...>, U>;
402 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
404 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
408 if( v.index() != I::value ) detail::throw_bad_variant_access();
409 return std::move( v._get_impl( I() ) );
414 template<class U, class... T> constexpr U const& get(variant<T...> const& v)
416 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
418 using I = mp11::mp_find<variant<T...>, U>;
420 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), v._get_impl( I() );
423 template<class U, class... T> constexpr U const&& get(variant<T...> const&& v)
425 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
427 using I = mp11::mp_find<variant<T...>, U>;
429 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
431 return ( v.index() != I::value? detail::throw_bad_variant_access(): (void)0 ), std::move( v._get_impl( I() ) );
435 if( v.index() != I::value ) detail::throw_bad_variant_access();
436 return std::move( v._get_impl( I() ) );
443 template<std::size_t I, class... T> constexpr typename std::add_pointer<variant_alternative_t<I, variant<T...>>>::type get_if(variant<T...>* v) noexcept
445 static_assert( I < sizeof...(T), "Index out of bounds" );
446 return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
449 template<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
451 static_assert( I < sizeof...(T), "Index out of bounds" );
452 return v && v->index() == I? &v->_get_impl( mp11::mp_size_t<I>() ): 0;
455 template<class U, class... T> constexpr typename std::add_pointer<U>::type get_if(variant<T...>* v) noexcept
457 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
459 using I = mp11::mp_find<variant<T...>, U>;
461 return v && v->index() == I::value? &v->_get_impl( I() ): 0;
464 template<class U, class... T> constexpr typename std::add_pointer<U const>::type get_if(variant<T...> const * v) noexcept
466 static_assert( mp11::mp_count<variant<T...>, U>::value == 1, "The type must occur exactly once in the list of variant alternatives" );
468 using I = mp11::mp_find<variant<T...>, U>;
470 return v && v->index() == I::value? &v->_get_impl( I() ): 0;
480 #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
482 template<class T> struct is_trivially_copy_constructible: mp11::mp_bool<std::is_copy_constructible<T>::value && std::has_trivial_copy_constructor<T>::value>
486 template<class T> struct is_trivially_copy_assignable: mp11::mp_bool<std::is_copy_assignable<T>::value && std::has_trivial_copy_assign<T>::value>
490 template<class T> struct is_trivially_move_constructible: mp11::mp_bool<std::is_move_constructible<T>::value && std::is_trivial<T>::value>
494 template<class T> struct is_trivially_move_assignable: mp11::mp_bool<std::is_move_assignable<T>::value && std::is_trivial<T>::value>
500 using std::is_trivially_copy_constructible;
501 using std::is_trivially_copy_assignable;
502 using std::is_trivially_move_constructible;
503 using std::is_trivially_move_assignable;
509 template<class D, class... T> union variant_storage_impl;
511 template<class... T> using variant_storage = variant_storage_impl<mp11::mp_all<std::is_trivially_destructible<T>...>, T...>;
513 template<class D> union variant_storage_impl<D>
517 // not all trivially destructible
518 template<class T1, class... T> union variant_storage_impl<mp11::mp_false, T1, T...>
521 variant_storage<T...> rest_;
523 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
527 template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
531 ~variant_storage_impl()
535 template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a )
537 ::new( &first_ ) T1( std::forward<A>(a)... );
540 template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
542 rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
545 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
546 constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
548 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>() ); }
549 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>() ); }
552 template<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...>
565 variant_storage<T...> rest_;
567 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
568 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
569 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
570 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
571 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
572 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
573 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
574 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
575 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
576 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
578 template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
580 ~variant_storage_impl()
584 template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
585 template<class... A> void emplace( mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
586 template<class... A> void emplace( mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
587 template<class... A> void emplace( mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
588 template<class... A> void emplace( mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
589 template<class... A> void emplace( mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
590 template<class... A> void emplace( mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
591 template<class... A> void emplace( mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
592 template<class... A> void emplace( mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
593 template<class... A> void emplace( mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
595 template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
597 rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
600 BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
601 constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
603 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
604 constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
606 BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
607 constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
609 BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
610 constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
612 BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
613 constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
615 BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
616 constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
618 BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
619 constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
621 BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
622 constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
624 BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
625 constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
627 BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
628 constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
630 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>() ); }
631 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>() ); }
634 // all trivially destructible
635 template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T...>
638 variant_storage<T...> rest_;
640 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
644 template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
648 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a )
650 ::new( &first_ ) T1( std::forward<A>(a)... );
653 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
655 rest_.emplace( mp11::mp_size_t<I-1>(), std::forward<A>(a)... );
658 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
660 *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
663 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
665 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)... );
668 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<0> ) noexcept { return first_; }
669 constexpr T1 const& get( mp11::mp_size_t<0> ) const noexcept { return first_; }
671 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>() ); }
672 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>() ); }
675 template<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...>
688 variant_storage<T...> rest_;
690 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
691 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
692 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
693 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
694 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
695 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
696 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
697 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
698 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
699 template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
701 template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
703 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
704 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
705 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
706 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
707 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
708 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
709 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
710 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
711 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
712 template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
714 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
716 rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
719 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
721 *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
724 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
726 this->emplace_impl( mp11::mp_all<
727 detail::is_trivially_move_assignable<T0>,
728 detail::is_trivially_move_assignable<T1>,
729 detail::is_trivially_move_assignable<T2>,
730 detail::is_trivially_move_assignable<T3>,
731 detail::is_trivially_move_assignable<T4>,
732 detail::is_trivially_move_assignable<T5>,
733 detail::is_trivially_move_assignable<T6>,
734 detail::is_trivially_move_assignable<T7>,
735 detail::is_trivially_move_assignable<T8>,
736 detail::is_trivially_move_assignable<T9>,
737 detail::is_trivially_move_assignable<T>...>(), mp11::mp_size_t<I>(), std::forward<A>(a)... );
740 BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
741 constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
743 BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
744 constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
746 BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
747 constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
749 BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
750 constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
752 BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
753 constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
755 BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
756 constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
758 BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
759 constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
761 BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
762 constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
764 BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
765 constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
767 BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
768 constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
770 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>() ); }
771 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>() ); }
774 // resolve_overload_*
776 template<class... T> struct overload;
778 template<> struct overload<>
780 void operator()() const;
783 template<class T1, class... T> struct overload<T1, T...>: overload<T...>
785 using overload<T...>::operator();
786 mp11::mp_identity<T1> operator()(T1) const;
789 #if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
791 template<class U, class... T> using resolve_overload_type_ = decltype( overload<T...>()(std::declval<U>()) );
793 template<class U, class... T> struct resolve_overload_type_impl: mp11::mp_defer< resolve_overload_type_, U, T... >
797 template<class U, class... T> using resolve_overload_type = typename resolve_overload_type_impl<U, T...>::type::type;
801 template<class U, class... T> using resolve_overload_type = typename decltype( overload<T...>()(std::declval<U>()) )::type;
805 template<class U, class... T> using resolve_overload_index = mp11::mp_find<mp11::mp_list<T...>, resolve_overload_type<U, T...>>;
809 template<bool is_trivially_destructible, bool is_single_buffered, class... T> struct variant_base_impl;
810 template<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...>;
814 // trivially destructible, single buffered
815 template<class... T> struct variant_base_impl<true, true, T...>
818 variant_storage<none, T...> st1_;
820 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
824 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
828 // requires: ix_ == 0
829 template<class I, class... A> void _replace( I, A&&... a )
831 ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
835 constexpr std::size_t index() const noexcept
840 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
842 size_t const J = I+1;
846 return st1_.get( mp11::mp_size_t<J>() );
849 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
851 // size_t const J = I+1;
852 // assert( ix_ == I+1 );
854 return st1_.get( mp11::mp_size_t<I+1>() );
857 template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, A&&... a )
859 static_assert( std::is_nothrow_constructible<U, A&&...>::value, "Logic error: U must be nothrow constructible from A&&..." );
861 st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
865 template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, A&&... a )
867 static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
869 U tmp( std::forward<A>(a)... );
871 st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
875 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
877 std::size_t const J = I+1;
878 using U = mp11::mp_at_c<variant<T...>, I>;
880 this->emplace_impl<J, U>( std::is_nothrow_constructible<U, A&&...>(), std::forward<A>(a)... );
884 // trivially destructible, double buffered
885 template<class... T> struct variant_base_impl<true, false, T...>
888 variant_storage<none, T...> st1_;
889 variant_storage<none, T...> st2_;
891 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
895 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
899 // requires: ix_ == 0
900 template<class I, class... A> void _replace( I, A&&... a )
902 ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
906 constexpr std::size_t index() const noexcept
908 return ix_ >= 0? ix_ - 1: -ix_ - 1;
911 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
913 size_t const J = I+1;
915 assert( ix_ == J || -ix_ == J );
917 constexpr mp11::mp_size_t<J> j{};
918 return ix_ >= 0? st1_.get( j ): st2_.get( j );
921 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
923 // size_t const J = I+1;
924 // assert( ix_ == J || -ix_ == J );
925 // constexpr mp_size_t<J> j{};
927 return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
930 template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
932 size_t const J = I+1;
936 st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
937 ix_ = -static_cast<int>( J );
941 st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
947 // not trivially destructible, single buffered
948 template<class... T> struct variant_base_impl<false, true, T...>
951 variant_storage<none, T...> st1_;
953 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
957 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
961 // requires: ix_ == 0
962 template<class I, class... A> void _replace( I, A&&... a )
964 ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
969 // using U = mp_at_c<mp_list<none, T...>, I>;
970 // st1_.get( I ).~U();
975 variant_base_impl * this_;
977 template<class I> void operator()( I ) const noexcept
979 using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
980 this_->st1_.get( I() ).~U();
984 void _destroy() noexcept
988 mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
992 ~variant_base_impl() noexcept
997 constexpr std::size_t index() const noexcept
1002 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
1004 size_t const J = I+1;
1008 return st1_.get( mp11::mp_size_t<J>() );
1011 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
1013 // size_t const J = I+1;
1014 // assert( ix_ == J );
1016 return st1_.get( mp11::mp_size_t<I+1>() );
1019 template<std::size_t I, class... A> void emplace( A&&... a )
1021 size_t const J = I+1;
1023 using U = mp11::mp_at_c<variant<T...>, I>;
1025 static_assert( std::is_nothrow_move_constructible<U>::value, "Logic error: U must be nothrow move constructible" );
1027 U tmp( std::forward<A>(a)... );
1031 st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
1036 // not trivially destructible, double buffered
1037 template<class... T> struct variant_base_impl<false, false, T...>
1040 variant_storage<none, T...> st1_;
1041 variant_storage<none, T...> st2_;
1043 constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
1047 template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
1051 // requires: ix_ == 0
1052 template<class I, class... A> void _replace( I, A&&... a )
1054 ::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
1059 // using U = mp_at_c<mp_list<none, T...>, I>;
1060 // st1_.get( I ).~U();
1065 variant_base_impl * this_;
1067 template<class I> void operator()( I ) const noexcept
1069 using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
1070 this_->st1_.get( I() ).~U();
1076 variant_base_impl * this_;
1078 template<class I> void operator()( I ) const noexcept
1080 using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
1081 this_->st2_.get( I() ).~U();
1085 void _destroy() noexcept
1089 mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
1093 mp11::mp_with_index<1 + sizeof...(T)>( -ix_, _destroy_L2{ this } );
1097 ~variant_base_impl() noexcept
1102 constexpr std::size_t index() const noexcept
1104 return ix_ >= 0? ix_ - 1: -ix_ - 1;
1107 template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
1109 size_t const J = I+1;
1111 assert( ix_ == J || -ix_ == J );
1113 constexpr mp11::mp_size_t<J> j{};
1114 return ix_ >= 0? st1_.get( j ): st2_.get( j );
1117 template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
1119 // size_t const J = I+1;
1120 // assert( ix_ == J || -ix_ == J );
1121 // constexpr mp_size_t<J> j{};
1123 return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
1126 template<std::size_t I, class... A> void emplace( A&&... a )
1128 size_t const J = I+1;
1132 st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
1135 ix_ = -static_cast<int>( J );
1139 st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
1147 } // namespace detail
1151 template<class T> struct in_place_type_t
1155 #if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
1157 template<class T> constexpr in_place_type_t<T> in_place_type{};
1164 template<class T> struct is_in_place_type: std::false_type {};
1165 template<class T> struct is_in_place_type<in_place_type_t<T>>: std::true_type {};
1167 } // namespace detail
1171 template<std::size_t I> struct in_place_index_t
1175 #if !defined(BOOST_NO_CXX14_VARIABLE_TEMPLATES)
1177 template<std::size_t I> constexpr in_place_index_t<I> in_place_index{};
1184 template<class T> struct is_in_place_index: std::false_type {};
1185 template<std::size_t I> struct is_in_place_index<in_place_index_t<I>>: std::true_type {};
1187 } // namespace detail
1189 // is_nothrow_swappable
1199 template<class T> using is_swappable_impl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
1201 #if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
1203 template<class T> struct is_nothrow_swappable_impl_
1205 static constexpr bool value = noexcept(swap(std::declval<T&>(), std::declval<T&>()));
1208 template<class T> using is_nothrow_swappable_impl = mp11::mp_bool< is_nothrow_swappable_impl_<T>::value >;
1212 template<class T> using is_nothrow_swappable_impl = typename std::enable_if<noexcept(swap(std::declval<T&>(), std::declval<T&>()))>::type;
1218 template<class T> struct is_swappable: mp11::mp_valid<det2::is_swappable_impl, T>
1222 #if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
1224 template<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>
1230 template<class T> struct is_nothrow_swappable: mp11::mp_valid<det2::is_nothrow_swappable_impl, T>
1238 template<bool CopyConstructible, bool TriviallyCopyConstructible, class... T> struct variant_cc_base_impl;
1240 template<class... T> using variant_cc_base = variant_cc_base_impl<
1241 mp11::mp_all<std::is_copy_constructible<T>...>::value,
1242 mp11::mp_all<detail::is_trivially_copy_constructible<T>...>::value,
1245 template<class... T> struct variant_cc_base_impl<true, true, T...>: public variant_base<T...>
1247 using variant_base = detail::variant_base<T...>;
1248 using variant_base::variant_base;
1250 variant_cc_base_impl() = default;
1251 variant_cc_base_impl( variant_cc_base_impl const& ) = default;
1252 variant_cc_base_impl( variant_cc_base_impl && ) = default;
1253 variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
1254 variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1257 template<bool B, class... T> struct variant_cc_base_impl<false, B, T...>: public variant_base<T...>
1259 using variant_base = detail::variant_base<T...>;
1260 using variant_base::variant_base;
1262 variant_cc_base_impl() = default;
1263 variant_cc_base_impl( variant_cc_base_impl const& ) = delete;
1264 variant_cc_base_impl( variant_cc_base_impl && ) = default;
1265 variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
1266 variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1269 template<class... T> struct variant_cc_base_impl<true, false, T...>: public variant_base<T...>
1271 using variant_base = detail::variant_base<T...>;
1272 using variant_base::variant_base;
1278 variant_cc_base_impl() = default;
1286 variant_base * this_;
1287 variant_base const & r;
1289 template<class I> void operator()( I i ) const
1291 this_->_replace( i, r._get_impl( i ) );
1297 variant_cc_base_impl( variant_cc_base_impl const& r )
1298 noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
1301 mp11::mp_with_index<sizeof...(T)>( r.index(), L1{ this, r } );
1306 variant_cc_base_impl( variant_cc_base_impl && ) = default;
1310 variant_cc_base_impl& operator=( variant_cc_base_impl const & ) = default;
1311 variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
1316 template<bool CopyAssignable, bool TriviallyCopyAssignable, class... T> struct variant_ca_base_impl;
1318 template<class... T> using variant_ca_base = variant_ca_base_impl<
1319 mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>::value,
1320 mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>::value,
1323 template<class... T> struct variant_ca_base_impl<true, true, T...>: public variant_cc_base<T...>
1325 using variant_base = detail::variant_cc_base<T...>;
1326 using variant_base::variant_base;
1328 variant_ca_base_impl() = default;
1329 variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1330 variant_ca_base_impl( variant_ca_base_impl && ) = default;
1331 variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = default;
1332 variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1335 template<bool B, class... T> struct variant_ca_base_impl<false, B, T...>: public variant_cc_base<T...>
1337 using variant_base = detail::variant_cc_base<T...>;
1338 using variant_base::variant_base;
1340 variant_ca_base_impl() = default;
1341 variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1342 variant_ca_base_impl( variant_ca_base_impl && ) = default;
1343 variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = delete;
1344 variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1347 template<class... T> struct variant_ca_base_impl<true, false, T...>: public variant_cc_base<T...>
1349 using variant_base = detail::variant_cc_base<T...>;
1350 using variant_base::variant_base;
1356 variant_ca_base_impl() = default;
1357 variant_ca_base_impl( variant_ca_base_impl const& ) = default;
1358 variant_ca_base_impl( variant_ca_base_impl && ) = default;
1366 variant_base * this_;
1367 variant_base const & r;
1369 template<class I> void operator()( I i ) const
1371 this_->template emplace<I::value>( r._get_impl( i ) );
1377 BOOST_CXX14_CONSTEXPR variant_ca_base_impl& operator=( variant_ca_base_impl const & r )
1378 noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
1380 mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
1386 variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
1391 template<bool MoveConstructible, bool TriviallyMoveConstructible, class... T> struct variant_mc_base_impl;
1393 template<class... T> using variant_mc_base = variant_mc_base_impl<
1394 mp11::mp_all<std::is_move_constructible<T>...>::value,
1395 mp11::mp_all<detail::is_trivially_move_constructible<T>...>::value,
1398 template<class... T> struct variant_mc_base_impl<true, true, T...>: public variant_ca_base<T...>
1400 using variant_base = detail::variant_ca_base<T...>;
1401 using variant_base::variant_base;
1403 variant_mc_base_impl() = default;
1404 variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1405 variant_mc_base_impl( variant_mc_base_impl && ) = default;
1406 variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
1407 variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1410 template<bool B, class... T> struct variant_mc_base_impl<false, B, T...>: public variant_ca_base<T...>
1412 using variant_base = detail::variant_ca_base<T...>;
1413 using variant_base::variant_base;
1415 variant_mc_base_impl() = default;
1416 variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1417 variant_mc_base_impl( variant_mc_base_impl && ) = delete;
1418 variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
1419 variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1422 template<class... T> struct variant_mc_base_impl<true, false, T...>: public variant_ca_base<T...>
1424 using variant_base = detail::variant_ca_base<T...>;
1425 using variant_base::variant_base;
1431 variant_mc_base_impl() = default;
1432 variant_mc_base_impl( variant_mc_base_impl const& ) = default;
1440 variant_base * this_;
1443 template<class I> void operator()( I i ) const
1445 this_->_replace( i, std::move( r._get_impl( i ) ) );
1451 variant_mc_base_impl( variant_mc_base_impl && r )
1452 noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
1454 mp11::mp_with_index<sizeof...(T)>( r.index(), L2{ this, r } );
1459 variant_mc_base_impl& operator=( variant_mc_base_impl const & ) = default;
1460 variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
1465 template<bool MoveAssignable, bool TriviallyMoveAssignable, class... T> struct variant_ma_base_impl;
1467 template<class... T> using variant_ma_base = variant_ma_base_impl<
1468 mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>::value,
1469 mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>::value,
1472 template<class... T> struct variant_ma_base_impl<true, true, T...>: public variant_mc_base<T...>
1474 using variant_base = detail::variant_mc_base<T...>;
1475 using variant_base::variant_base;
1477 variant_ma_base_impl() = default;
1478 variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1479 variant_ma_base_impl( variant_ma_base_impl && ) = default;
1480 variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
1481 variant_ma_base_impl& operator=( variant_ma_base_impl && ) = default;
1484 template<bool B, class... T> struct variant_ma_base_impl<false, B, T...>: public variant_mc_base<T...>
1486 using variant_base = detail::variant_mc_base<T...>;
1487 using variant_base::variant_base;
1489 variant_ma_base_impl() = default;
1490 variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1491 variant_ma_base_impl( variant_ma_base_impl && ) = default;
1492 variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
1493 variant_ma_base_impl& operator=( variant_ma_base_impl && ) = delete;
1496 template<class... T> struct variant_ma_base_impl<true, false, T...>: public variant_mc_base<T...>
1498 using variant_base = detail::variant_mc_base<T...>;
1499 using variant_base::variant_base;
1505 variant_ma_base_impl() = default;
1506 variant_ma_base_impl( variant_ma_base_impl const& ) = default;
1507 variant_ma_base_impl( variant_ma_base_impl && ) = default;
1511 variant_ma_base_impl& operator=( variant_ma_base_impl const & ) = default;
1519 variant_base * this_;
1522 template<class I> void operator()( I i ) const
1524 this_->template emplace<I::value>( std::move( r._get_impl( i ) ) );
1530 variant_ma_base_impl& operator=( variant_ma_base_impl && r )
1531 noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
1533 mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
1538 } // namespace detail
1542 template<class... T> class variant: private detail::variant_ma_base<T...>
1546 using variant_base = detail::variant_ma_base<T...>;
1552 template<class E1 = void, class E2 = mp11::mp_if<std::is_default_constructible< mp11::mp_first<variant<T...>> >, E1>>
1554 noexcept( std::is_nothrow_default_constructible< mp11::mp_first<variant<T...>> >::value )
1555 : variant_base( mp11::mp_size_t<0>() )
1559 // variant( variant const& ) = default;
1560 // variant( variant && ) = default;
1563 class Ud = typename std::decay<U>::type,
1564 class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
1565 class V = detail::resolve_overload_type<U&&, T...>,
1566 class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type
1568 constexpr variant( U&& u )
1569 noexcept( std::is_nothrow_constructible<V, U&&>::value )
1570 : variant_base( detail::resolve_overload_index<U&&, T...>(), std::forward<U>(u) )
1574 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>
1575 constexpr explicit variant( in_place_type_t<U>, A&&... a ): variant_base( I(), std::forward<A>(a)... )
1579 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>
1580 constexpr explicit variant( in_place_type_t<U>, std::initializer_list<V> il, A&&... a ): variant_base( I(), il, std::forward<A>(a)... )
1584 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>
1585 constexpr explicit variant( in_place_index_t<I>, A&&... a ): variant_base( mp11::mp_size_t<I>(), std::forward<A>(a)... )
1589 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>
1590 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)... )
1596 // variant& operator=( variant const& ) = default;
1597 // variant& operator=( variant && ) = default;
1600 class E1 = typename std::enable_if<!std::is_same<typename std::decay<U>::type, variant>::value>::type,
1601 class V = detail::resolve_overload_type<U, T...>,
1602 class E2 = typename std::enable_if<std::is_assignable<V&, U&&>::value && std::is_constructible<V, U&&>::value>::type
1604 BOOST_CXX14_CONSTEXPR variant& operator=( U&& u )
1605 noexcept( std::is_nothrow_constructible<V, U&&>::value )
1607 std::size_t const I = detail::resolve_overload_index<U, T...>::value;
1608 this->template emplace<I>( std::forward<U>(u) );
1614 template<class U, class... A,
1615 class E = typename std::enable_if< mp11::mp_count<variant<T...>, U>::value == 1 && std::is_constructible<U, A&&...>::value >::type>
1616 BOOST_CXX14_CONSTEXPR U& emplace( A&&... a )
1618 using I = mp11::mp_find<variant<T...>, U>;
1619 variant_base::template emplace<I::value>( std::forward<A>(a)... );
1620 return _get_impl( I() );
1623 template<class U, class V, class... A,
1624 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>
1625 BOOST_CXX14_CONSTEXPR U& emplace( std::initializer_list<V> il, A&&... a )
1627 using I = mp11::mp_find<variant<T...>, U>;
1628 variant_base::template emplace<I::value>( il, std::forward<A>(a)... );
1629 return _get_impl( I() );
1632 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>
1633 BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( A&&... a )
1635 variant_base::template emplace<I>( std::forward<A>(a)... );
1636 return _get_impl( mp11::mp_size_t<I>() );
1639 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>
1640 BOOST_CXX14_CONSTEXPR variant_alternative_t<I, variant<T...>>& emplace( std::initializer_list<V> il, A&&... a )
1642 variant_base::template emplace<I>( il, std::forward<A>(a)... );
1643 return _get_impl( mp11::mp_size_t<I>() );
1648 constexpr bool valueless_by_exception() const noexcept
1653 using variant_base::index;
1664 template<class I> void operator()( I i ) const
1667 swap( this_->_get_impl( i ), r._get_impl( i ) );
1673 void swap( variant& r ) noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>..., detail::is_nothrow_swappable<T>...>::value )
1675 if( index() == r.index() )
1677 mp11::mp_with_index<sizeof...(T)>( index(), L5{ this, r } );
1681 variant tmp( std::move(*this) );
1682 *this = std::move( r );
1683 r = std::move( tmp );
1687 // private accessors
1689 using variant_base::_get_impl;
1691 // converting constructors (extension)
1695 template<class... U> struct L6
1697 variant_base * this_;
1698 variant<U...> const & r;
1700 template<class I> void operator()( I i ) const
1702 using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
1703 this_->_replace( J{}, r._get_impl( i ) );
1709 template<class... U,
1710 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1711 variant( variant<U...> const& r )
1712 noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<U>...>::value )
1714 mp11::mp_with_index<sizeof...(U)>( r.index(), L6<U...>{ this, r } );
1719 template<class... U> struct L7
1721 variant_base * this_;
1724 template<class I> void operator()( I i ) const
1726 using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
1727 this_->_replace( J{}, std::move( r._get_impl( i ) ) );
1733 template<class... U,
1734 class E2 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1735 variant( variant<U...> && r )
1736 noexcept( mp11::mp_all<std::is_nothrow_move_constructible<U>...>::value )
1738 mp11::mp_with_index<sizeof...(U)>( r.index(), L7<U...>{ this, r } );
1741 // subset (extension)
1745 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 )
1747 return variant<U...>( in_place_index_t<J>(), std::forward<V>(v) );
1750 template<class... U, class V> static variant<U...> _subset_impl( mp11::mp_size_t<sizeof...(U)>, V && /*v*/ )
1752 detail::throw_bad_variant_access();
1757 template<class... U> struct L8
1761 template<class I> variant<U...> operator()( I i ) const
1763 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1764 return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
1770 template<class... U,
1771 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1772 BOOST_CXX14_CONSTEXPR variant<U...> subset() &
1774 return mp11::mp_with_index<sizeof...(T)>( index(), L8<U...>{ this } );
1779 template<class... U> struct L9
1781 variant const * this_;
1783 template<class I> variant<U...> operator()( I i ) const
1785 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1786 return this_->_subset_impl<U...>( J{}, this_->_get_impl( i ) );
1792 template<class... U,
1793 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1794 constexpr variant<U...> subset() const&
1796 return mp11::mp_with_index<sizeof...(T)>( index(), L9<U...>{ this } );
1801 template<class... U> struct L10
1805 template<class I> variant<U...> operator()( I i ) const
1807 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1808 return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
1814 template<class... U,
1815 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1816 BOOST_CXX14_CONSTEXPR variant<U...> subset() &&
1818 return mp11::mp_with_index<sizeof...(T)>( index(), L10<U...>{ this } );
1821 #if !BOOST_WORKAROUND(BOOST_GCC, < 40900)
1823 // g++ 4.8 doesn't handle const&& particularly well
1827 template<class... U> struct L11
1829 variant const * this_;
1831 template<class I> variant<U...> operator()( I i ) const
1833 using J = mp11::mp_find<mp11::mp_list<U...>, mp11::mp_at<mp11::mp_list<T...>, I>>;
1834 return this_->_subset_impl<U...>( J{}, std::move( this_->_get_impl( i ) ) );
1840 template<class... U,
1841 class E2 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<U>..., mp11::mp_contains<mp11::mp_list<T...>, U>...>, void> >
1842 constexpr variant<U...> subset() const&&
1844 return mp11::mp_with_index<sizeof...(T)>( index(), L11<U...>{ this } );
1850 // relational operators
1855 template<class... T> struct eq_L
1857 variant<T...> const & v;
1858 variant<T...> const & w;
1860 template<class I> constexpr bool operator()( I i ) const
1862 return v._get_impl( i ) == w._get_impl( i );
1866 } // namespace detail
1868 template<class... T> constexpr bool operator==( variant<T...> const & v, variant<T...> const & w )
1870 return v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::eq_L<T...>{ v, w } );
1876 template<class... T> struct ne_L
1878 variant<T...> const & v;
1879 variant<T...> const & w;
1881 template<class I> constexpr bool operator()( I i ) const
1883 return v._get_impl( i ) != w._get_impl( i );
1887 } // namespace detail
1889 template<class... T> constexpr bool operator!=( variant<T...> const & v, variant<T...> const & w )
1891 return v.index() != w.index() || mp11::mp_with_index<sizeof...(T)>( v.index(), detail::ne_L<T...>{ v, w } );
1897 template<class... T> struct lt_L
1899 variant<T...> const & v;
1900 variant<T...> const & w;
1902 template<class I> constexpr bool operator()( I i ) const
1904 return v._get_impl( i ) < w._get_impl( i );
1908 } // namespace detail
1910 template<class... T> constexpr bool operator<( variant<T...> const & v, variant<T...> const & w )
1912 return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::lt_L<T...>{ v, w } ) );
1915 template<class... T> constexpr bool operator>( variant<T...> const & v, variant<T...> const & w )
1923 template<class... T> struct le_L
1925 variant<T...> const & v;
1926 variant<T...> const & w;
1928 template<class I> constexpr bool operator()( I i ) const
1930 return v._get_impl( i ) <= w._get_impl( i );
1934 } // namespace detail
1936 template<class... T> constexpr bool operator<=( variant<T...> const & v, variant<T...> const & w )
1938 return v.index() < w.index() || ( v.index() == w.index() && mp11::mp_with_index<sizeof...(T)>( v.index(), detail::le_L<T...>{ v, w } ) );
1941 template<class... T> constexpr bool operator>=( variant<T...> const & v, variant<T...> const & w )
1950 template<class T> using remove_cv_ref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
1952 template<class... T> variant<T...> const & extract_variant_base_( variant<T...> const & );
1954 #if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
1956 template<class V> struct extract_vbase_impl
1958 using type = decltype( extract_variant_base_( std::declval<V>() ) );
1961 template<class V> using extract_variant_base = remove_cv_ref_t< typename extract_vbase_impl<V>::type >;
1965 template<class V> using extract_variant_base = remove_cv_ref_t< decltype( extract_variant_base_( std::declval<V>() ) ) >;
1969 template<class V> using variant_base_size = variant_size< extract_variant_base<V> >;
1971 template<class T, class U> struct copy_cv_ref
1976 template<class T, class U> struct copy_cv_ref<T, U const>
1978 using type = T const;
1981 template<class T, class U> struct copy_cv_ref<T, U volatile>
1983 using type = T volatile;
1986 template<class T, class U> struct copy_cv_ref<T, U const volatile>
1988 using type = T const volatile;
1991 template<class T, class U> struct copy_cv_ref<T, U&>
1993 using type = typename copy_cv_ref<T, U>::type&;
1996 template<class T, class U> struct copy_cv_ref<T, U&&>
1998 using type = typename copy_cv_ref<T, U>::type&&;
2001 template<class T, class U> using copy_cv_ref_t = typename copy_cv_ref<T, U>::type;
2003 template<class F> struct Qret
2005 template<class... T> using fn = decltype( std::declval<F>()( std::declval<T>()... ) );
2008 template<class L> using front_if_same = mp11::mp_if<mp11::mp_apply<mp11::mp_same, L>, mp11::mp_front<L>>;
2010 template<class V> using apply_cv_ref = mp11::mp_product<copy_cv_ref_t, extract_variant_base<V>, mp11::mp_list<V>>;
2014 #if !BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
2016 template<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>...> >;
2020 template<class R, class F, class... V> struct Vret_impl
2022 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>...> >;
2025 template<class R, class F, class... V> using Vret = typename Vret_impl<R, F, V...>::type;
2029 } // namespace detail
2031 template<class R = detail::deduced, class F> constexpr auto visit( F&& f ) -> detail::Vret<R, F>
2033 return std::forward<F>(f)();
2039 template<class R, class F, class V1> struct visit_L1
2044 template<class I> auto operator()( I ) const -> Vret<R, F, V1>
2046 return std::forward<F>(f)( unsafe_get<I::value>( std::forward<V1>(v1) ) );
2050 } // namespace detail
2052 template<class R = detail::deduced, class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<R, F, V1>
2054 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) } );
2057 #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) || BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
2062 template<class F, class A> struct bind_front_
2067 template<class... T> auto operator()( T&&... t ) -> decltype( std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... ) )
2069 return std::forward<F>(f)( std::forward<A>(a), std::forward<T>(t)... );
2073 template<class F, class A> bind_front_<F, A> bind_front( F&& f, A&& a )
2075 return bind_front_<F, A>{ std::forward<F>(f), std::forward<A>(a) };
2078 template<class R, class F, class V1, class V2> struct visit_L2
2085 template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2>
2087 auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2088 return visit<R>( f2, std::forward<V2>(v2) );
2092 } // namespace detail
2094 template<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>
2096 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) } );
2102 template<class R, class F, class V1, class V2, class V3> struct visit_L3
2110 template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3>
2112 auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2113 return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
2117 } // namespace detail
2119 template<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>
2121 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) } );
2127 template<class R, class F, class V1, class V2, class V3, class V4> struct visit_L4
2136 template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3, V4>
2138 auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
2139 return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
2143 } // namespace detail
2145 template<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>
2147 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) } );
2152 template<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...>
2154 return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), [&]( auto I ){
2156 auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( detail::unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
2157 return visit<R>( f2, std::forward<V2>(v2), std::forward<V>(v)... );
2164 // specialized algorithms
2165 template<class... T,
2166 class E = typename std::enable_if<mp11::mp_all<std::is_move_constructible<T>..., detail::is_swappable<T>...>::value>::type>
2167 void swap( variant<T...> & v, variant<T...> & w )
2168 noexcept( noexcept(v.swap(w)) )
2178 template<class V> struct hash_value_L
2182 template<class I> std::size_t operator()( I ) const
2184 boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
2185 boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;
2194 auto const & t = unsafe_get<I::value>( v );
2196 hv ^= std::hash<remove_cv_ref_t<decltype(t)>>()( t );
2199 return static_cast<std::size_t>( hv );
2203 } // namespace detail
2205 inline std::size_t hash_value( monostate const & )
2210 template<class... T> std::size_t hash_value( variant<T...> const & v )
2212 return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< variant<T...> >{ v } );
2218 template<class T> using is_hash_enabled = std::is_default_constructible< std::hash<typename std::remove_const<T>::type> >;
2220 template<class V, bool E = mp11::mp_all_of<V, is_hash_enabled>::value> struct std_hash_impl;
2222 template<class V> struct std_hash_impl<V, false>
2224 std_hash_impl() = delete;
2225 std_hash_impl( std_hash_impl const& ) = delete;
2226 std_hash_impl& operator=( std_hash_impl const& ) = delete;
2229 template<class V> struct std_hash_impl<V, true>
2231 std::size_t operator()( V const & v ) const
2233 return hash_value( v );
2237 } // namespace detail
2239 } // namespace variant2
2240 } // namespace boost
2245 template<class... T> struct hash< ::boost::variant2::variant<T...> >: public ::boost::variant2::detail::std_hash_impl< ::boost::variant2::variant<T...> >
2249 template<> struct hash< ::boost::variant2::monostate >
2251 std::size_t operator()( ::boost::variant2::monostate const & v ) const
2253 return hash_value( v );
2259 #if defined(_MSC_VER) && _MSC_VER < 1910
2260 # pragma warning( pop )
2263 #endif // #ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED