C++11 标准::forward_as_tuple 和标准::前进
C++11 std::forward_as_tuple and std::forward
当我使用函数参数作为std::forward_as_tuple
参数时,我应该std::forward
函数参数吗?
template<class ... List>
void fn(List&& ... list){
// do I need this forward?
call_fn( forward_as_tuple( forward<List>(list)... ) );
}
我知道它们将被存储为右值引用,但是我还应该考虑什么吗?
您必须使用 std::forward
才能保留要fn()
的参数的值类别。由于参数在fn
内有一个名称,它们是左值,如果没有std::forward
它们将始终以这样的方式传递给std::forward_as_tuple
。
可以使用以下示例来演示差异:
template<typename T>
void bar2(T&& t)
{
std::cout << __PRETTY_FUNCTION__ << ' '
<< std::is_rvalue_reference<decltype(t)>::value << 'n';
}
template<typename T>
void bar1(T&& t)
{
std::cout << __PRETTY_FUNCTION__ << ' '
<< std::is_rvalue_reference<decltype(t)>::value << 'n';
bar2(std::forward<T>(t));
bar2(t);
}
bar1
总是把它的参数传递给bar2
,一次有std::forward
,一次没有。现在让我们用左值和右值参数来调用它们。
foo f;
bar1(f);
std::cout << "--------n";
bar1(foo{});
输出:
void bar1(T&&) [with T = foo&] 0
void bar2(T&&) [with T = foo&] 0
void bar2(T&&) [with T = foo&] 0
--------
void bar1(T&&) [with T = foo] 1
void bar2(T&&) [with T = foo] 1
void bar2(T&&) [with T = foo&] 0
从输出中可以看出,在这两种情况下,不使用std::forward
,参数都作为左值传递给bar2
。
是的,您几乎肯定想在这里使用std::forward
,这是假设在调用 call_fn
之后不使用 list
中的参数。这是std::forward
的典型用例,因为您希望练习完美转发的语义。
std::forward
保留其参数的值类别(即左值作为左值,右值作为右值(。 反过来,std::forward_as_tuple
也会做同样的事情,就好像std::tuple<List&&...>(std::forward<List>(list)...)
被召唤一样。
关于"存储为右值引用"的说明。并不是说参数包中List
的参数都是右值引用(它们可能是(,而是在此上下文中推导List
,因此引用折叠将适用,推导的类型可以是右值引用或左值引用。在创建std::tuple
的过程中,您希望保持/保留的正是这种区别。
是的,如果你想保留完美的转发语义。在您的示例中:
template<class ... List>
void fn(List&& ... list)
类型 List&&
,其中 List
实际上是模板参数,是通用引用而不是 R 值引用。因此,您应该将它们std::forward
std::forward_as_tuple
函数,否则在std::forward_as_tuple
内部,由于引用折叠,传递给fn
的 r 值引用将显示为 l 值引用。
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 铸造标准::有没有回到原来的类型
- 重新定位图像时如何前进到下一个内存块
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 标准库类型的赋值运算符的引用限定符
- 在前进的同时更改FOV(视野)
- 标准是否严格定义了该程序应该如何编译?
- 如何从Windows应用程序输出到标准?
- 安全到标准:移动会员?
- 如何正确将字符串转换为标准::时间::system_clock::time_point?
- 完美前进和使用标准::前进<T>
- C++11 标准::forward_as_tuple 和标准::前进
- C++ 标准::前进<T> vs static_cast<T>
- 标准::移动,标准::前进,值类型和模板扣除