C++ 可以避免元组上重复std::move()吗?

C++ 可以避免元组上重复std::move()吗?,c++,c++11,move-semantics,rvalue-reference,stdtuple,C++,C++11,Move Semantics,Rvalue Reference,Stdtuple,假设我有一个元组和一个函数: typedef std::tuple< std::unqiue_ptr<int>, std::unqiue_ptr<char> > SomeTuple; void someFunction( std::unqiue_ptr<int>, std::unqiue_ptr<char> ); 显然不起作用,因为rt是一个左值。那么,有没有办法避免对每个std::get重复多次std::move

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

typedef std::tuple< std::unqiue_ptr<int>, std::unqiue_ptr<char> > SomeTuple;          
void someFunction( std::unqiue_ptr<int>, std::unqiue_ptr<char> );
显然不起作用,因为rt是一个
左值
。那么,有没有办法避免对每个
std::get
重复多次
std::move()

它可以从C++14获得,但可以用C++11实现:

因此,您需要一个额外的功能,但可以避免这种重复:

void unroll( SomeTuple &t )
{
    someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
void展开(SomeTuple&t)
{
someFunction(std::get(std::move(t)),std::get(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>{});
}
模板
void unroll\u impl(SomeTuple&t,std::integer\u序列)
{
someFunction(std::get(std::move(t))…);
}
无效展开(SomeTuple&t)
{
展开impl(t,std::make_index_sequence{});
}
但是您必须为此创建一个助手函数。

您可能需要使用

它可以从C++14获得,但可以用C++11实现:

因此,您需要一个额外的功能,但可以避免这种重复:

void unroll( SomeTuple &t )
{
    someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
void展开(SomeTuple&t)
{
someFunction(std::get(std::move(t)),std::get(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>{});
}
模板
void unroll\u impl(SomeTuple&t,std::integer\u序列)
{
someFunction(std::get(std::move(t))…);
}
无效展开(SomeTuple&t)
{
展开impl(t,std::make_index_sequence{});
}

但是您必须为此创建一个helper函数。

从语义上讲,您无法避免使用
std::move
。要获得右值,您需要要么没有某个名称(因此不能引用它两次),要么用
std::move
删除该名称。并且
t
有一个名称,但是要将
unique\u ptr
传递给函数调用,您需要它没有名称

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


从语义上讲,您无法避免使用
std::move
。要获得右值,您需要要么没有某个名称(因此不能引用它两次),要么用
std::move
删除该名称。并且
t
有一个名称,但是要将
unique\u ptr
传递给函数调用,您需要它没有名称

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


如果不指定类型,则必须使用
std::make_index_sequence
(默认情况下将使用
size_t
),而不是
std::make_integer_sequence
。我相信你不需要
typename
也不需要
::type()
t
在包扩展后不会被多次移动吗?@0x499602D2:它会被多次传递到
std::move
,但是
std::tuple
rvalue引用上的
std::get
将返回对第N个元素的rvalue引用。当在
unroll\u impl
中对
someFunction
调用求值时,该函数将从中移动。简单地说,
std::get(std::move(t))
完全等同于
std::move(std::get(t))
当您不指定必须使用的类型时,
std::make_index_sequence
(默认情况下将使用
size_t
),而不是
std::make_integer_sequence
。我相信你不需要
typename
也不需要
::type()
t
在包扩展后不会被多次移动吗?@0x499602D2:它会被多次传递到
std::move
,但是
std::tuple
rvalue引用上的
std::get
将返回对第N个元素的rvalue引用。当在
unroll\u impl
中对
someFunction
调用求值时,该函数将从中移动。简单地说,
std::get(std::move(t))
完全等同于
std::move(std::get(t))
为了真正避免重复,可以从众多“分解元组”实现中选择一种,它允许您将元组“分解”为匹配函数调用的参数。所谓的感谢(AFAIK)关于这个主题的爷爷介绍。您所需要的只是可变模板,但如果您有C++14,您可以获得更简单的实现,例如,为了真正避免重复,请获取许多“分解元组”实现中的一个,它允许您将元组“分解”为匹配函数调用的参数。所谓的感谢(AFAIK)关于这个主题的爷爷介绍。你所需要的只是可变模板,但是如果你有C++14,你可以得到更简单的实现,例如。,
void unroll( SomeTuple &t )
{
  someFunction( std::move( std::get<0>( t ) ), std::move( std::get<1>( t ) ) );
}
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() );
}