是否可以避免在元组上重复 std::move()

Is it possible to avoid repetition of std::move() on a tuple?

本文关键字:std move 可以避免 元组 是否      更新时间:2023-10-16

假设我有一个元组和一个函数:

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传递给函数调用,您需要它没有名称。

例如,您可以通过将展开更改为(更惯用?

void unroll( SomeTuple &t )
{
  someFunction( std::move( std::get<0>( t ) ), std::move( std::get<1>( t ) ) );
}

任何解决方案都将涉及对每个unique_ptr函数参数的std::move(),或者调用返回右值或右值引用的另一个函数。

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() );
}