forked from boostorg/variant2
Add proper type deduction to visit_by_index
This commit is contained in:
@ -2213,27 +2213,27 @@ void swap( variant<T...> & v, variant<T...> & w )
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<class V, class... F> struct visit_by_index_L
|
template<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>> >;
|
||||||
|
|
||||||
|
template<class R, class V, class... F> struct visit_by_index_L
|
||||||
{
|
{
|
||||||
V&& v;
|
V&& v;
|
||||||
std::tuple<F&&...> tp;
|
std::tuple<F&&...> tp;
|
||||||
|
|
||||||
template<class I> void operator()( I ) const
|
template<class I> constexpr detail::Vret2<R, V, F...> operator()( I ) const
|
||||||
{
|
{
|
||||||
std::get<I::value>( std::move(tp) )( unsafe_get<I::value>( std::forward<V>(v) ) );
|
return std::get<I::value>( std::move(tp) )( unsafe_get<I::value>( std::forward<V>(v) ) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<class V, class... F> void visit_by_index( V&& v, F&&... f )
|
template<class R = detail::deduced, class V, class... F> constexpr auto visit_by_index( V&& v, F&&... f ) -> detail::Vret2<R, V, F...>
|
||||||
{
|
{
|
||||||
constexpr auto N = variant_size<V>::value;
|
static_assert( variant_size<V>::value == sizeof...(F), "Incorrect number of function objects" );
|
||||||
|
|
||||||
static_assert( N == sizeof...(F), "Incorrect number of function objects" );
|
return mp11::mp_with_index<variant_size<V>::value>( v.index(),
|
||||||
|
detail::visit_by_index_L<R, V, F...>{ std::forward<V>(v), std::tuple<F&&...>( std::forward<F>(f)... ) } );
|
||||||
mp11::mp_with_index<N>( v.index(),
|
|
||||||
detail::visit_by_index_L<V, F...>{ std::forward<V>(v), std::tuple<F&&...>( std::forward<F>(f)... ) } );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashing support
|
// hashing support
|
||||||
|
@ -4,9 +4,32 @@
|
|||||||
|
|
||||||
#include <boost/variant2/variant.hpp>
|
#include <boost/variant2/variant.hpp>
|
||||||
#include <boost/core/lightweight_test.hpp>
|
#include <boost/core/lightweight_test.hpp>
|
||||||
|
#include <boost/core/lightweight_test_trait.hpp>
|
||||||
|
#include <boost/mp11.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
using namespace boost::variant2;
|
using namespace boost::variant2;
|
||||||
|
using boost::mp11::mp_int;
|
||||||
|
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct F1
|
||||||
|
{
|
||||||
|
int operator()( X& ) const { return 1; }
|
||||||
|
int operator()( X const& ) const { return 2; }
|
||||||
|
int operator()( X&& ) const { return 3; }
|
||||||
|
int operator()( X const&& ) const { return 4; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct F2
|
||||||
|
{
|
||||||
|
mp_int<1> operator()( X& ) const { return {}; }
|
||||||
|
mp_int<2> operator()( X const& ) const { return {}; }
|
||||||
|
mp_int<3> operator()( X&& ) const { return {}; }
|
||||||
|
mp_int<4> operator()( X const&& ) const { return {}; }
|
||||||
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@ -20,7 +43,7 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
variant<int const, int, float const> v( 1 );
|
variant<int const, int, float const> v( in_place_index_t<0>(), 1 );
|
||||||
|
|
||||||
visit_by_index( v,
|
visit_by_index( v,
|
||||||
[]( int const& x ){ BOOST_TEST_EQ( x, 1 ); },
|
[]( int const& x ){ BOOST_TEST_EQ( x, 1 ); },
|
||||||
@ -46,5 +69,58 @@ int main()
|
|||||||
[]( float const& x ){ BOOST_TEST_EQ( x, 3.14f ); } );
|
[]( float const& x ){ BOOST_TEST_EQ( x, 3.14f ); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
variant<int, float> const v( 7 );
|
||||||
|
|
||||||
|
auto r = visit_by_index( v,
|
||||||
|
[]( int const& x ) -> double { return x; },
|
||||||
|
[]( float const& x ) -> double { return x; } );
|
||||||
|
|
||||||
|
BOOST_TEST_TRAIT_SAME( decltype(r), double );
|
||||||
|
BOOST_TEST_EQ( r, 7.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
variant<int, float> const v( 2.0f );
|
||||||
|
|
||||||
|
auto r = visit_by_index( v,
|
||||||
|
[]( int const& x ) { return x + 0.0; },
|
||||||
|
[]( float const& x ) { return x + 0.0; } );
|
||||||
|
|
||||||
|
BOOST_TEST_TRAIT_SAME( decltype(r), double );
|
||||||
|
BOOST_TEST_EQ( r, 2.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
variant<int, float, double> const v( 3.0 );
|
||||||
|
|
||||||
|
auto r = visit_by_index<double>( v,
|
||||||
|
[]( int const& x ) { return x; },
|
||||||
|
[]( float const& x ) { return x; },
|
||||||
|
[]( double const& x ) { return x; } );
|
||||||
|
|
||||||
|
BOOST_TEST_TRAIT_SAME( decltype(r), double );
|
||||||
|
BOOST_TEST_EQ( r, 3.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
variant<X> v;
|
||||||
|
variant<X> const cv;
|
||||||
|
|
||||||
|
F1 f1;
|
||||||
|
|
||||||
|
BOOST_TEST_EQ( visit_by_index( v, f1 ), 1 );
|
||||||
|
BOOST_TEST_EQ( visit_by_index( cv, f1 ), 2 );
|
||||||
|
BOOST_TEST_EQ( visit_by_index( std::move( v ), f1 ), 3 );
|
||||||
|
BOOST_TEST_EQ( visit_by_index( std::move( cv ), f1 ), 4 );
|
||||||
|
|
||||||
|
F2 f2;
|
||||||
|
|
||||||
|
BOOST_TEST_EQ( visit_by_index<int>( v, f2 ), 1 );
|
||||||
|
BOOST_TEST_EQ( visit_by_index<int>( cv, f2 ), 2 );
|
||||||
|
BOOST_TEST_EQ( visit_by_index<int>( std::move( v ), f2 ), 3 );
|
||||||
|
BOOST_TEST_EQ( visit_by_index<int>( std::move( cv ), f2 ), 4 );
|
||||||
|
}
|
||||||
|
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user