1
0
forked from boostorg/mp11

Add test/tuple_transform_2.cpp

This commit is contained in:
Peter Dimov
2020-05-23 21:13:35 +03:00
parent 0ee00ee64a
commit 9349a82e6b
3 changed files with 175 additions and 6 deletions

View File

@@ -42,9 +42,15 @@ Returns `std::forward<F>(f)`.
template<class F, class... Tp> constexpr /*...*/ tuple_transform(F const& f, Tp&&... tp);
`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>(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.
(`std::tuple`, `std::pair` and `std::array` are considered tuples.)
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, as if 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` (lvalue
references are preserved, rvalue references are returned by value.)
The order in which the elements of the tuples are processed is unspecified. Calling `f` should not have
side effects.

View File

@@ -157,6 +157,7 @@ compile tuple_apply_cx.cpp ;
run construct_from_tuple.cpp ;
compile construct_from_tuple_cx.cpp ;
run tuple_transform.cpp ;
run tuple_transform_2.cpp ;
compile tuple_transform_cx.cpp ;
# set

162
test/tuple_transform_2.cpp Normal file
View File

@@ -0,0 +1,162 @@
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/tuple.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/core/lightweight_test.hpp>
#include <tuple>
#include <utility>
#include <array>
#include <cstddef>
int f( int x )
{
return x + 1;
}
int g( int x, int y )
{
return x + y;
}
int h( int x, int y, int z )
{
return x + y + z;
}
int q( int x, int y, int z, int v )
{
return x + y + z + v;
}
template<class T1, class... T> std::array<T1, 1 + sizeof...(T)> make_array( T1 t1, T... t )
{
return { { t1, t... } };
}
template<class Tp> struct test_element
{
Tp& tp;
template<int I> void operator()( boost::mp11::mp_int<I> ) const
{
BOOST_TEST_EQ( std::get<I>( tp ), q( I, I, I, I ) );
}
};
int main()
{
using boost::mp11::tuple_transform;
//
{
std::tuple<int> r = tuple_transform( f, std::make_tuple( 1 ) );
BOOST_TEST_EQ( std::get<0>( r ), 2 );
}
{
std::tuple<int> r = tuple_transform( f, ::make_array( 1 ) );
BOOST_TEST_EQ( std::get<0>( r ), 2 );
}
{
std::tuple<int> r = tuple_transform( g, ::make_array( 1 ), std::make_tuple( 2 ) );
BOOST_TEST_EQ( std::get<0>( r ), 3 );
}
{
std::tuple<int> r = tuple_transform( h, ::make_array( 1 ), std::make_tuple( 2 ), ::make_array( 3 ) );
BOOST_TEST_EQ( std::get<0>( r ), 6 );
}
//
{
std::tuple<int, int> r = tuple_transform( f, std::make_tuple( 1, 2 ) );
BOOST_TEST_EQ( std::get<0>( r ), 2 );
BOOST_TEST_EQ( std::get<1>( r ), 3 );
}
{
std::tuple<int, int> r = tuple_transform( f, std::make_pair( 1, 2 ) );
BOOST_TEST_EQ( std::get<0>( r ), 2 );
BOOST_TEST_EQ( std::get<1>( r ), 3 );
}
{
std::tuple<int, int> r = tuple_transform( f, ::make_array( 1, 2 ) );
BOOST_TEST_EQ( std::get<0>( r ), 2 );
BOOST_TEST_EQ( std::get<1>( r ), 3 );
}
{
std::tuple<int, int> r = tuple_transform( g, ::make_array( 1, 2 ), std::make_pair( 3, 4 ) );
BOOST_TEST_EQ( std::get<0>( r ), 4 );
BOOST_TEST_EQ( std::get<1>( r ), 6 );
}
{
std::tuple<int, int> r = tuple_transform( h, ::make_array( 1, 2 ), std::make_pair( 3, 4 ), std::make_tuple( 5, 6 ) );
BOOST_TEST_EQ( std::get<0>( r ), 9 );
BOOST_TEST_EQ( std::get<1>( r ), 12 );
}
//
{
std::tuple<int, int, int> r = tuple_transform( f, std::make_tuple( 1, 2, 3 ) );
BOOST_TEST_EQ( std::get<0>( r ), 2 );
BOOST_TEST_EQ( std::get<1>( r ), 3 );
BOOST_TEST_EQ( std::get<2>( r ), 4 );
}
{
std::tuple<int, int, int> r = tuple_transform( f, ::make_array( 1, 2, 3 ) );
BOOST_TEST_EQ( std::get<0>( r ), 2 );
BOOST_TEST_EQ( std::get<1>( r ), 3 );
BOOST_TEST_EQ( std::get<2>( r ), 4 );
}
{
std::tuple<int, int, int> r = tuple_transform( g, ::make_array( 1, 2, 3 ), std::make_tuple( 4, 5, 6 ) );
BOOST_TEST_EQ( std::get<0>( r ), 5 );
BOOST_TEST_EQ( std::get<1>( r ), 7 );
BOOST_TEST_EQ( std::get<2>( r ), 9 );
}
{
std::tuple<int, int, int> r = tuple_transform( h, ::make_array( 1, 2, 3 ), std::make_tuple( 4, 5, 6 ), ::make_array( 7, 8, 9 ) );
BOOST_TEST_EQ( std::get<0>( r ), 12 );
BOOST_TEST_EQ( std::get<1>( r ), 15 );
BOOST_TEST_EQ( std::get<2>( r ), 18 );
}
{
using namespace boost::mp11;
int const N = 64;
using Tp = mp_rename<mp_iota< mp_int<N> >, std::tuple>;
auto const r = tuple_transform( q, Tp(), Tp(), Tp(), Tp() );
mp_for_each<Tp>( test_element<decltype(r)>{ r } );
}
return boost::report_errors();
}