Reputation: 44258
Let's say I have a tuple and a function:
typedef std::tuple< std::unqiue_ptr<int>, std::unqiue_ptr<char> > SomeTuple;
void someFunction( std::unqiue_ptr<int>, std::unqiue_ptr<char> );
so in a helper function I am unrolling tuple into arguments:
void unroll( SomeTuple &t )
{
someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
It works, but I want to avoid repeating of std::move
multiple times. Naive solutions like:
void unroll( SomeTuple &t )
{
auto &&rt = std::move( t );
someFunction( std::get<0>( rt ), std::get<1>( rt ) );
}
obviosly does not work, as rt is a lvalue
. So is there a way to avoid repeating std::move()
multiple times for each std::get
?
Upvotes: 0
Views: 357
Reputation: 1476
Semantically, you can't avoid the std::move
. To get an rvalue, you need to either not have a name for something (so you can't refer to it twice) or strip the name with std::move
. And t
has a name, but to pass a unique_ptr
to a function call, you need it to not have a name.
You can see this for example by changing unroll to the (more idiomatic?)
void unroll( SomeTuple &t )
{
someFunction( std::move( std::get<0>( t ) ), std::move( std::get<1>( t ) ) );
}
Any solution is going to involve either a std::move()
on each unique_ptr
function parameter, or a call to another function that returns an rvalue or rvalue reference.
void unroll( SomeTuple &t )
{
auto get0 = [&]()->std::unique_ptr<int>&& { return std::move(std::get<0>(t)); };
auto get1 = [&]()->std::unique_ptr<char> { return std::move(std::get<1>(t)); };
someFunction( get0(), get1() );
}
Upvotes: 1
Reputation: 204
You may want to use std::integer_sequence
It is available from C++14 but can be implemented with C++11 : https://github.com/serge-sans-paille/pythran/blob/master/pythran/pythonic/include/utils/seq.hpp
Thanks to this, you need an extra function but you avoid this repetition :
void unroll( SomeTuple &t )
{
someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
becomes
template<size_t ...I>
void unroll_impl( SomeTuple &t , std::integer_sequence<I...>)
{
someFunction( std::get<I>( std::move( t ) )...);
}
void unroll( SomeTuple &t )
{
unroll_impl( t, std::make_index_sequence<2>{});
}
But you have to create an helper function for this.
Upvotes: 5