diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index 84eba30..e36f376 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -2208,6 +2208,34 @@ void swap( variant & v, variant & w ) v.swap( w ); } +// visit_by_index + +namespace detail +{ + +template struct visit_by_index_L +{ + V&& v; + std::tuple tp; + + template void operator()( I ) const + { + std::get( std::move(tp) )( unsafe_get( std::forward(v) ) ); + } +}; + +} // namespace detail + +template void visit_by_index( V&& v, F&&... f ) +{ + constexpr auto N = variant_size::value; + + static_assert( N == sizeof...(F), "Incorrect number of function objects" ); + + mp11::mp_with_index( v.index(), + detail::visit_by_index_L{ std::forward(v), std::tuple( std::forward(f)... ) } ); +} + // hashing support namespace detail diff --git a/test/Jamfile b/test/Jamfile index d104a1b..f62221c 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -121,3 +121,5 @@ run variant_visit_r.cpp : : : ; compile variant_derived_construct.cpp ; + +run variant_visit_by_index.cpp ; diff --git a/test/variant_visit_by_index.cpp b/test/variant_visit_by_index.cpp new file mode 100644 index 0000000..e1939b4 --- /dev/null +++ b/test/variant_visit_by_index.cpp @@ -0,0 +1,50 @@ +// Copyright 2017, 2021 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +using namespace boost::variant2; + +int main() +{ + { + variant v; + + visit_by_index( v, + []( int& x ){ BOOST_TEST_EQ( x, 0 ); }, + []( int& ){ BOOST_ERROR( "incorrect alternative" ); }, + []( float& ){ BOOST_ERROR( "incorrect alternative" ); } ); + } + + { + variant v( 1 ); + + visit_by_index( v, + []( int const& x ){ BOOST_TEST_EQ( x, 1 ); }, + []( int& ){ BOOST_ERROR( "incorrect alternative" ); }, + []( float const& ){ BOOST_ERROR( "incorrect alternative" ); } ); + } + + { + variant const v( in_place_index_t<1>(), 2 ); + + visit_by_index( v, + []( int const& ){ BOOST_ERROR( "incorrect alternative" ); }, + []( int const& x ){ BOOST_TEST_EQ( x, 2 ); }, + []( float const& ){ BOOST_ERROR( "incorrect alternative" ); } ); + } + + { + variant const v( 3.14f ); + + visit_by_index( v, + []( int const& ){ BOOST_ERROR( "incorrect alternative" ); }, + []( int const& ){ BOOST_ERROR( "incorrect alternative" ); }, + []( float const& x ){ BOOST_TEST_EQ( x, 3.14f ); } ); + } + + return boost::report_errors(); +}