forked from boostorg/variant2
Add support for visit<R>
This commit is contained in:
@@ -2009,11 +2009,26 @@ template<class L> using front_if_same = mp11::mp_if<mp11::mp_apply<mp11::mp_same
|
||||
|
||||
template<class V> using apply_cv_ref = mp11::mp_product<copy_cv_ref_t, extract_variant_base<V>, mp11::mp_list<V>>;
|
||||
|
||||
template<class F, class... V> using Vret = front_if_same<mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...>>;
|
||||
struct deduced {};
|
||||
|
||||
#if !BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
|
||||
|
||||
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>...> >;
|
||||
|
||||
#else
|
||||
|
||||
template<class R, class F, class... V> struct Vret_impl
|
||||
{
|
||||
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>...> >;
|
||||
};
|
||||
|
||||
template<class R, class F, class... V> using Vret = typename Vret_impl<R, F, V...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class F> constexpr auto visit( F&& f ) -> decltype(std::forward<F>(f)())
|
||||
template<class R = detail::deduced, class F> constexpr auto visit( F&& f ) -> detail::Vret<R, F>
|
||||
{
|
||||
return std::forward<F>(f)();
|
||||
}
|
||||
@@ -2021,12 +2036,12 @@ template<class F> constexpr auto visit( F&& f ) -> decltype(std::forward<F>(f)()
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class F, class V1> struct visit_L1
|
||||
template<class R, class F, class V1> struct visit_L1
|
||||
{
|
||||
F&& f;
|
||||
V1&& v1;
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1>
|
||||
template<class I> auto operator()( I ) const -> Vret<R, F, V1>
|
||||
{
|
||||
return std::forward<F>(f)( unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
}
|
||||
@@ -2034,9 +2049,9 @@ template<class F, class V1> struct visit_L1
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<F, V1>
|
||||
template<class R = detail::deduced, class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<R, F, V1>
|
||||
{
|
||||
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L1<F, V1>{ std::forward<F>(f), std::forward<V1>(v1) } );
|
||||
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) } );
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) || BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
|
||||
@@ -2060,31 +2075,31 @@ template<class F, class A> bind_front_<F, A> bind_front( F&& f, A&& a )
|
||||
return bind_front_<F, A>{ std::forward<F>(f), std::forward<A>(a) };
|
||||
}
|
||||
|
||||
template<class F, class V1, class V2> struct visit_L2
|
||||
template<class R, class F, class V1, class V2> struct visit_L2
|
||||
{
|
||||
F&& f;
|
||||
|
||||
V1&& v1;
|
||||
V2&& v2;
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1, V2>
|
||||
template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2>
|
||||
{
|
||||
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
return visit( f2, std::forward<V2>(v2) );
|
||||
return visit<R>( f2, std::forward<V2>(v2) );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class F, class V1, class V2> constexpr auto visit( F&& f, V1&& v1, V2&& v2 ) -> detail::Vret<F, V1, V2>
|
||||
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>
|
||||
{
|
||||
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L2<F, V1, V2>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2) } );
|
||||
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) } );
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class F, class V1, class V2, class V3> struct visit_L3
|
||||
template<class R, class F, class V1, class V2, class V3> struct visit_L3
|
||||
{
|
||||
F&& f;
|
||||
|
||||
@@ -2092,24 +2107,24 @@ template<class F, class V1, class V2, class V3> struct visit_L3
|
||||
V2&& v2;
|
||||
V3&& v3;
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3>
|
||||
template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3>
|
||||
{
|
||||
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
|
||||
return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class F, class V1, class V2, class V3> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3 ) -> detail::Vret<F, V1, V2, V3>
|
||||
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>
|
||||
{
|
||||
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L3<F, V1, V2, V3>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3) } );
|
||||
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) } );
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class F, class V1, class V2, class V3, class V4> struct visit_L4
|
||||
template<class R, class F, class V1, class V2, class V3, class V4> struct visit_L4
|
||||
{
|
||||
F&& f;
|
||||
|
||||
@@ -2118,28 +2133,28 @@ template<class F, class V1, class V2, class V3, class V4> struct visit_L4
|
||||
V3&& v3;
|
||||
V4&& v4;
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3, V4>
|
||||
template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3, V4>
|
||||
{
|
||||
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
|
||||
return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<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<F, V1, V2, V3, V4>
|
||||
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>
|
||||
{
|
||||
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L4<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) } );
|
||||
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) } );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<class F, class V1, class V2, class... V> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V&&... v ) -> detail::Vret<F, V1, V2, V...>
|
||||
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...>
|
||||
{
|
||||
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), [&]( auto I ){
|
||||
|
||||
auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( detail::unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
|
||||
return visit( f2, std::forward<V2>(v2), std::forward<V>(v)... );
|
||||
return visit<R>( f2, std::forward<V2>(v2), std::forward<V>(v)... );
|
||||
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user