是否可以避免在元组上重复 std::move() ?
Is it possible to avoid repetition of std::move() on a tuple?
假设我有一个元组和一个函数:
typedef std::tuple< std::unqiue_ptr<int>, std::unqiue_ptr<char> > SomeTuple;
void someFunction( std::unqiue_ptr<int>, std::unqiue_ptr<char> );
所以在辅助函数中,我将元组展开为参数:
void unroll( SomeTuple &t )
{
someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
它有效,但我想避免多次重复 std::move
。天真的解决方案,如:
void unroll( SomeTuple &t )
{
auto &&rt = std::move( t );
someFunction( std::get<0>( rt ), std::get<1>( rt ) );
}
显然是行不通的,因为 rt 是 lvalue
。那么有没有办法避免为每个 std::get
重复 std::move()
多次?
您可能想使用 std::integer_sequence
它在 C++14 中可用,但可以用 C++11 实现:https://github.com/serge-sans-paille/pythran/blob/master/pythran/pythonic/include/utils/seq.hpp
多亏了这个,你需要一个额外的功能,但你避免了这种重复:
void unroll( SomeTuple &t )
{
someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
变成
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>{});
}
但是你必须为此创建一个辅助函数。
从语义上讲,您无法避免 std::move
。要获得右值,您需要没有某物的名称(因此您不能引用它两次)或使用 std::move
去除名称。 t
有名字,但是要将 unique_ptr
传递给函数调用,您需要它没有名字。
例如,您可以将 unroll 更改为(更惯用?)
void unroll( SomeTuple &t )
{
someFunction( std::move( std::get<0>( t ) ), std::move( std::get<1>( t ) ) );
}
任何解决方案都将涉及每个 unique_ptr
函数参数的 std::move()
,或者调用另一个 returns 右值或右值引用的函数。
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() );
}
假设我有一个元组和一个函数:
typedef std::tuple< std::unqiue_ptr<int>, std::unqiue_ptr<char> > SomeTuple;
void someFunction( std::unqiue_ptr<int>, std::unqiue_ptr<char> );
所以在辅助函数中,我将元组展开为参数:
void unroll( SomeTuple &t )
{
someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
它有效,但我想避免多次重复 std::move
。天真的解决方案,如:
void unroll( SomeTuple &t )
{
auto &&rt = std::move( t );
someFunction( std::get<0>( rt ), std::get<1>( rt ) );
}
显然是行不通的,因为 rt 是 lvalue
。那么有没有办法避免为每个 std::get
重复 std::move()
多次?
您可能想使用 std::integer_sequence
它在 C++14 中可用,但可以用 C++11 实现:https://github.com/serge-sans-paille/pythran/blob/master/pythran/pythonic/include/utils/seq.hpp
多亏了这个,你需要一个额外的功能,但你避免了这种重复:
void unroll( SomeTuple &t )
{
someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
变成
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>{});
}
但是你必须为此创建一个辅助函数。
从语义上讲,您无法避免 std::move
。要获得右值,您需要没有某物的名称(因此您不能引用它两次)或使用 std::move
去除名称。 t
有名字,但是要将 unique_ptr
传递给函数调用,您需要它没有名字。
例如,您可以将 unroll 更改为(更惯用?)
void unroll( SomeTuple &t )
{
someFunction( std::move( std::get<0>( t ) ), std::move( std::get<1>( t ) ) );
}
任何解决方案都将涉及每个 unique_ptr
函数参数的 std::move()
,或者调用另一个 returns 右值或右值引用的函数。
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() );
}