forked from boostorg/mp11
Replace implementation of tuple_transform
This commit is contained in:
@ -37,14 +37,14 @@ expression `f(std::get<J>(std::forward<Tp>(tp)))` for `J` in 0..`N-1`, where `N`
|
||||
|
||||
Returns `std::forward<F>(f)`.
|
||||
|
||||
## tuple_transform(f, tp)
|
||||
## tuple_transform(f, tp...)
|
||||
|
||||
template<class F, class... Tps> constexpr /*...*/ tuple_transform(F const& f, Tps const&... tps);
|
||||
template<class F, class... Tp> constexpr /*...*/ tuple_transform(F const& f, Tp&&... tp);
|
||||
|
||||
`tuple_transform(f, tps...)` accepts a function object `f` followed by one or more tuples of equal length
|
||||
`tuple_transform(f, tp...)` accepts a function object `f` followed by one or more tuples of equal length
|
||||
(`std::pair` is also accepted). The callable `f` must accept as many arguments as there are tuples. The
|
||||
function object is called with the first elements of each tuple, then with the second element of each tuple,
|
||||
and so on, by evaluating the expression `f(std::get<J>(tps)...)` for `J` in 0..`N-1`, where `N` is
|
||||
`std::tuple_size<Tp>::value` for the first tuple `Tp`. The results are returned as a `Tp<Ts...>` with `Ts...`
|
||||
deduced from the return values of `f`. Warning: The order in which the elements of the tuples are processed
|
||||
is undefined. Calling `f` should not have side-effects.
|
||||
and so on, by evaluating the expression `f(std::get<J>(std::forward<Tp>(tp))...)` for `J` in 0..`N-1`, where
|
||||
`N` is the length of the tuples. The results are returned as a `std::tuple<T...>` with `T...` deduced from the
|
||||
return values of `f`. The order in which the elements of the tuples are processed is unspecified. Calling `f`
|
||||
should not have side effects.
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef BOOST_MP11_TUPLE_HPP_INCLUDED
|
||||
#define BOOST_MP11_TUPLE_HPP_INCLUDED
|
||||
|
||||
// Copyright 2015, 2017 Peter Dimov.
|
||||
// Copyright 2015-2020 Peter Dimov.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
@ -90,77 +90,33 @@ template<class Tp, class F> BOOST_MP11_CONSTEXPR F tuple_for_each( Tp && tp, F &
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class Tp, class F, class... Tps>
|
||||
struct tuple_transform_caller {
|
||||
F const& f_;
|
||||
std::tuple<Tp const&, Tps const&...> const tps_;
|
||||
|
||||
BOOST_MP11_CONSTEXPR tuple_transform_caller( Tp const& tp, F const& f, Tps const&... tps )
|
||||
: f_{f}, tps_{tp, tps...} {}
|
||||
|
||||
template <std::size_t J, std::size_t... I>
|
||||
BOOST_MP11_CONSTEXPR auto operator()(
|
||||
std::integral_constant<std::size_t, J>,
|
||||
integer_sequence<std::size_t, I...>) const
|
||||
-> decltype(f_(std::get<J>(std::get<I>(tps_))...))
|
||||
{
|
||||
return f_(std::get<J>(std::get<I>(tps_))...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tp, class F>
|
||||
struct tuple_transform_caller<Tp, F> {
|
||||
F const& f_;
|
||||
Tp const& tp_;
|
||||
|
||||
BOOST_MP11_CONSTEXPR tuple_transform_caller( Tp const& tp, F const& f )
|
||||
: f_{f}, tp_{tp} {}
|
||||
|
||||
template <std::size_t J>
|
||||
BOOST_MP11_CONSTEXPR auto operator()(
|
||||
std::integral_constant<std::size_t, J>,
|
||||
integer_sequence<std::size_t, 0>
|
||||
) const
|
||||
-> decltype(f_(std::get<J>(tp_)))
|
||||
{
|
||||
return f_(std::get<J>(tp_));
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
template <class...> class Tp,
|
||||
class... Ts,
|
||||
class... Us,
|
||||
std::size_t... J,
|
||||
class Seq = make_index_sequence<sizeof...(Us)>, // tuple sequence
|
||||
class R = Tp<decltype(std::declval<tuple_transform_caller<Tp<Ts...>, Us...>>()(
|
||||
std::integral_constant<std::size_t, J>{}, Seq{}
|
||||
))...>
|
||||
>
|
||||
BOOST_MP11_CONSTEXPR R tuple_transform_impl(
|
||||
tuple_transform_caller<Tp<Ts...>, Us...> c,
|
||||
integer_sequence<std::size_t, J...>)
|
||||
template<std::size_t J, class... Tp>
|
||||
BOOST_MP11_CONSTEXPR auto tp_extract( Tp&&... tp )
|
||||
-> decltype( std::forward_as_tuple( std::get<J>( std::forward<Tp>( tp ) )... ) )
|
||||
{
|
||||
return R( c(std::integral_constant<std::size_t, J>{}, Seq{})... );
|
||||
return std::forward_as_tuple( std::get<J>( std::forward<Tp>( tp ) )... );
|
||||
}
|
||||
|
||||
template<class... T> BOOST_MP11_CONSTEXPR auto tp_forward( T&&... t ) -> std::tuple<T...>
|
||||
{
|
||||
return std::tuple<T...>( std::forward<T>( t )... );
|
||||
}
|
||||
|
||||
template<class F, class... Tp, std::size_t... J>
|
||||
BOOST_MP11_CONSTEXPR auto tuple_transform_impl( integer_sequence<std::size_t, J...>, F const& f, Tp&&... tp )
|
||||
-> decltype( tp_forward( tuple_apply( f, tp_extract<J>( std::forward<Tp>(tp)... ) )... ) )
|
||||
{
|
||||
return tp_forward( tuple_apply( f, tp_extract<J>( std::forward<Tp>(tp)... ) )... );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// warning: evaluation order is undefined
|
||||
template<
|
||||
class F,
|
||||
class Tp,
|
||||
class... Tps,
|
||||
class Seq = make_index_sequence<std::tuple_size<Tp>::value> // element sequence
|
||||
>
|
||||
BOOST_MP11_CONSTEXPR auto tuple_transform( F const& f, Tp const& tp, Tps const&... tps )
|
||||
-> decltype(detail::tuple_transform_impl(
|
||||
std::declval<detail::tuple_transform_caller<Tp, F, Tps...>>(), Seq{}
|
||||
))
|
||||
template<class F, class Tp1, class... Tp,
|
||||
class Seq = make_index_sequence<std::tuple_size<typename std::remove_reference<Tp1>::type>::value>>
|
||||
BOOST_MP11_CONSTEXPR auto tuple_transform( F const& f, Tp1&& tp1, Tp&&... tp )
|
||||
-> decltype( detail::tuple_transform_impl( Seq(), f, std::forward<Tp1>(tp1), std::forward<Tp>(tp)... ) )
|
||||
{
|
||||
return detail::tuple_transform_impl(
|
||||
detail::tuple_transform_caller<Tp, F, Tps...>{ tp, f, tps... }, Seq{}
|
||||
);
|
||||
return detail::tuple_transform_impl( Seq(), f, std::forward<Tp1>(tp1), std::forward<Tp>(tp)... );
|
||||
}
|
||||
|
||||
} // namespace mp11
|
||||
|
@ -115,25 +115,25 @@ int main()
|
||||
std::pair<T<3>, T<4>> tp2;
|
||||
|
||||
{
|
||||
std::pair<T<2>, T<3>> s = tuple_transform( F{}, tp );
|
||||
std::tuple<T<2>, T<3>> s = tuple_transform( F{}, tp );
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 3 );
|
||||
BOOST_TEST_EQ( std::get<1>(s).value, 4 );
|
||||
}
|
||||
|
||||
{
|
||||
std::pair<T<2>, T<3>> s = tuple_transform( F{}, std::move(tp) );
|
||||
std::tuple<T<2>, T<3>> s = tuple_transform( F{}, std::move(tp) );
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 3 );
|
||||
BOOST_TEST_EQ( std::get<1>(s).value, 4 );
|
||||
}
|
||||
|
||||
{
|
||||
std::pair<T<4>, T<6>> s = tuple_transform( F{}, tp, tp2 );
|
||||
std::tuple<T<4>, T<6>> s = tuple_transform( F{}, tp, tp2 );
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 5 );
|
||||
BOOST_TEST_EQ( std::get<1>(s).value, 7 );
|
||||
}
|
||||
|
||||
{
|
||||
std::pair<T<4>, T<6>> s = tuple_transform(
|
||||
std::tuple<T<4>, T<6>> s = tuple_transform(
|
||||
F{}, std::move(tp), std::move(tp2)
|
||||
);
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 5 );
|
||||
@ -146,25 +146,25 @@ int main()
|
||||
std::pair<T<3>, T<4>> const tp2;
|
||||
|
||||
{
|
||||
std::pair<T<2>, T<3>> s = tuple_transform( F{}, tp );
|
||||
std::tuple<T<2>, T<3>> s = tuple_transform( F{}, tp );
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 3 );
|
||||
BOOST_TEST_EQ( std::get<1>(s).value, 4 );
|
||||
}
|
||||
|
||||
{
|
||||
std::pair<T<2>, T<3>> s = tuple_transform( F{}, std::move(tp) );
|
||||
std::tuple<T<2>, T<3>> s = tuple_transform( F{}, std::move(tp) );
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 3 );
|
||||
BOOST_TEST_EQ( std::get<1>(s).value, 4 );
|
||||
}
|
||||
|
||||
{
|
||||
std::pair<T<4>, T<6>> s = tuple_transform( F{}, tp, tp2 );
|
||||
std::tuple<T<4>, T<6>> s = tuple_transform( F{}, tp, tp2 );
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 5 );
|
||||
BOOST_TEST_EQ( std::get<1>(s).value, 7 );
|
||||
}
|
||||
|
||||
{
|
||||
std::pair<T<4>, T<6>> s = tuple_transform(
|
||||
std::tuple<T<4>, T<6>> s = tuple_transform(
|
||||
F{}, std::move(tp), std::move(tp2)
|
||||
);
|
||||
BOOST_TEST_EQ( std::get<0>(s).value, 5 );
|
||||
|
Reference in New Issue
Block a user