11#ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
22#define BOOST_VARIANT2_VARIANT_HPP_INCLUDED
33
4- // Copyright 2017-2019 Peter Dimov.
5- //
4+ // Copyright 2017-2026 Peter Dimov.
65// 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
6+ // https://www.boost.org/LICENSE_1_0.txt
107
118#if defined(_MSC_VER) && _MSC_VER < 1910
129# pragma warning( push )
@@ -451,61 +448,106 @@ template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T
451448
452449// get (type)
453450
454- template <class U , class ... T> constexpr U& get (variant<T...>& v)
451+ namespace detail
452+ {
453+
454+ template <class U , class V > struct get_if_impl_L1
455455{
456- static_assert ( mp11::mp_count<variant<T...>, U>::value == 1 , " The type must occur exactly once in the list of variant alternatives " ) ;
456+ V& v_ ;
457457
458- using I = mp11::mp_find<variant<T...>, U>;
458+ template <class I > constexpr U* fn ( I, mp11::mp_true ) const noexcept
459+ {
460+ return &v_._get_impl ( I () );
461+ }
462+
463+ template <class I > constexpr U* fn ( I, mp11::mp_false ) const noexcept
464+ {
465+ return nullptr ;
466+ }
459467
460- return ( v.index () != I::value? detail::throw_bad_variant_access (): (void )0 ), v._get_impl ( I () );
468+ template <class I > constexpr U* operator ()( I ) const noexcept
469+ {
470+ return this ->fn ( I (), std::is_same<U, mp11::mp_at<V, I>>() );
471+ }
472+ };
473+
474+ template <class U , class ... T> constexpr U* get_if_impl ( variant<T...>& v ) noexcept
475+ {
476+ return mp11::mp_with_index<sizeof ...(T)>( v.index (), get_if_impl_L1< U, variant<T...> >{ v } );
461477}
462478
463- template <class U , class ... T> constexpr U&& get(variant<T...>&& v)
479+ template <class U , class V > struct get_if_impl_L2
480+ {
481+ V const & v_;
482+
483+ template <class I > constexpr U const * fn ( I, mp11::mp_true ) const noexcept
484+ {
485+ return &v_._get_impl ( I () );
486+ }
487+
488+ template <class I > constexpr U const * fn ( I, mp11::mp_false ) const noexcept
489+ {
490+ return nullptr ;
491+ }
492+
493+ template <class I > constexpr U const * operator ()( I ) const noexcept
494+ {
495+ return this ->fn ( I (), std::is_same<U, mp11::mp_at<V, I>>() );
496+ }
497+ };
498+
499+ template <class U , class ... T> constexpr U const * get_if_impl ( variant<T...> const & v ) noexcept
464500{
465- static_assert ( mp11::mp_count<variant<T...>, U>::value == 1 , " The type must occur exactly once in the list of variant alternatives" );
501+ return mp11::mp_with_index<sizeof ...(T)>( v.index (), get_if_impl_L2< U, variant<T...> >{ v } );
502+ }
503+
504+ } // namespace detail
466505
467- using I = mp11::mp_find<variant<T...>, U>;
506+ template <class U , class ... T> constexpr U& get (variant<T...>& v)
507+ {
508+ static_assert ( mp11::mp_contains<variant<T...>, U>::value == 1 , " The type must be present in the list of variant alternatives" );
509+ return ( !holds_alternative<U>( v )? detail::throw_bad_variant_access (): (void )0 ), *detail::get_if_impl<U>( v );
510+ }
511+
512+ template <class U , class ... T> constexpr U&& get(variant<T...>&& v)
513+ {
514+ static_assert ( mp11::mp_contains<variant<T...>, U>::value == 1 , " The type must be present in the list of variant alternatives" );
468515
469516#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
470517
471- return ( v. index () != I::value ? detail::throw_bad_variant_access (): (void )0 ), std::move ( v. _get_impl ( I () ) );
518+ return ( !holds_alternative<U>( v ) ? detail::throw_bad_variant_access (): (void )0 ), std::move ( *detail::get_if_impl<U>( v ) );
472519
473520#else
474521
475- if ( v. index () != I::value ) detail::throw_bad_variant_access ();
476- return std::move ( v. _get_impl ( I () ) );
522+ if ( !holds_alternative<U>( v ) ) detail::throw_bad_variant_access ();
523+ return std::move ( *detail::get_if_impl<U>( v ) );
477524
478525#endif
479526}
480527
481528template <class U , class ... T> constexpr U const & get (variant<T...> const & v)
482529{
483- static_assert ( mp11::mp_count<variant<T...>, U>::value == 1 , " The type must occur exactly once in the list of variant alternatives" );
484-
485- using I = mp11::mp_find<variant<T...>, U>;
486-
487- return ( v.index () != I::value? detail::throw_bad_variant_access (): (void )0 ), v._get_impl ( I () );
530+ static_assert ( mp11::mp_contains<variant<T...>, U>::value == 1 , " The type must be present in the list of variant alternatives" );
531+ return ( !holds_alternative<U>( v )? detail::throw_bad_variant_access (): (void )0 ), *detail::get_if_impl<U>( v );
488532}
489533
490534template <class U , class ... T> constexpr U const && get(variant<T...> const && v)
491535{
492- static_assert ( mp11::mp_count<variant<T...>, U>::value == 1 , " The type must occur exactly once in the list of variant alternatives" );
493-
494- using I = mp11::mp_find<variant<T...>, U>;
536+ static_assert ( mp11::mp_contains<variant<T...>, U>::value == 1 , " The type must be present in the list of variant alternatives" );
495537
496538#if !BOOST_WORKAROUND(BOOST_MSVC, < 1930)
497539
498- return ( v. index () != I::value ? detail::throw_bad_variant_access (): (void )0 ), std::move ( v. _get_impl ( I () ) );
540+ return ( !holds_alternative<U>( v ) ? detail::throw_bad_variant_access (): (void )0 ), std::move ( *detail::get_if_impl<U>( v ) );
499541
500542#else
501543
502- if ( v. index () != I::value ) detail::throw_bad_variant_access ();
503- return std::move ( v. _get_impl ( I () ) );
544+ if ( !holds_alternative<U>( v ) ) detail::throw_bad_variant_access ();
545+ return std::move ( *detail::get_if_impl<U>( v ) );
504546
505547#endif
506548}
507549
508- // get_if
550+ // get_if (index)
509551
510552template <std::size_t I, class ... T> constexpr typename std::add_pointer<variant_alternative_t <I, variant<T...>>>::type get_if (variant<T...>* v) noexcept
511553{
@@ -519,22 +561,18 @@ template<std::size_t I, class... T> constexpr typename std::add_pointer<const va
519561 return v && v->index () == I? &v->_get_impl ( mp11::mp_size_t <I>() ): 0 ;
520562}
521563
564+ // get_if (type)
565+
522566template <class U , class ... T> constexpr typename std::add_pointer<U>::type get_if (variant<T...>* v) noexcept
523567{
524- static_assert ( mp11::mp_count<variant<T...>, U>::value == 1 , " The type must occur exactly once in the list of variant alternatives" );
525-
526- using I = mp11::mp_find<variant<T...>, U>;
527-
528- return v && v->index () == I::value? &v->_get_impl ( I () ): 0 ;
568+ static_assert ( mp11::mp_contains<variant<T...>, U>::value == 1 , " The type must be present in the list of variant alternatives" );
569+ return v && holds_alternative<U>( *v )? detail::get_if_impl<U>( *v ): 0 ;
529570}
530571
531- template <class U , class ... T> constexpr typename std::add_pointer<U const >::type get_if (variant<T...> const * v) noexcept
572+ template <class U , class ... T> constexpr typename std::add_pointer<U const >::type get_if (variant<T...> const * v) noexcept
532573{
533- static_assert ( mp11::mp_count<variant<T...>, U>::value == 1 , " The type must occur exactly once in the list of variant alternatives" );
534-
535- using I = mp11::mp_find<variant<T...>, U>;
536-
537- return v && v->index () == I::value? &v->_get_impl ( I () ): 0 ;
574+ static_assert ( mp11::mp_contains<variant<T...>, U>::value == 1 , " The type must be present in the list of variant alternatives" );
575+ return v && holds_alternative<U>( *v )? detail::get_if_impl<U>( *v ): 0 ;
538576}
539577
540578//
0 commit comments