这是转发参考吗?

时间:2016-11-26 13:54:15

标签: c++ c++11 perfect-forwarding forwarding-reference

在这个例子中,斯科特迈耶斯已经明确了右值引用和转发引用之间的区别:

Widget&& var1 = someWidget;     // here, “&&” means rvalue reference (1)

auto&& var2 = var1;             // here, “&&” does not mean rvalue reference (2)

template<typename T>
void f(std::vector<T>&& param); // here, “&&” means rvalue reference (3)

template<typename T>
void f(T&& param);              // here, “&&”does not mean rvalue reference (4)

基本上,当我们有一个可推导的上下文时就会出现这种区别,因此case(3)明确指出我们有一个vector<...>&&而{(1)}就是{4}。根据&#34;值类别&#34;进行推断和(在应用参考折叠规则之后)。

但更复杂的模式匹配会发生什么?以下列情况为例:

T

template <template <class...> class Tuple, class... Ts> void f(Tuple<Ts...>&& arg) { } 在这里意味着什么?

3 个答案:

答案 0 :(得分:16)

在上一个示例中,arg是左值参考。

  

转发参考是对cv非合格模板参数的右值参考

Tuple<Ts...>不是模板参数。

(来自[temp.deduct.call]的引文。)

答案 1 :(得分:11)

这是一个右值参考,而不是转发参考。

最简单的方法是尝试传递一个左值,如果它失败了,那么它是一个右值引用,如果没有,那么转发引用:

template<typename... Ts>
struct foo {};

//f function definition

int main() {
    foo<int, double> bar;
    f(bar); // fails! Cannot bind lvalue to rvalue reference
    f(foo<int, double>{}); // ok, rvalue is passed
}

答案 2 :(得分:4)

概念转发参考不是一个标准概念,当你看到它时,它很有用,但是如果你想要正确理解和处理它,你必须理解参考算法。 (我相信梅耶的书也有一章关于它)

转发参考概念的背后是参考算法:

  • &安培;&安培; &安培;&安培; =&amp;&amp;
  • &安培;&安培; &安培; =&amp;
  • &安培; &安培;&安培; =&amp;
  • &安培; &安培; =&amp;

让我们用转发参考模拟编译器模板类型推导

template<class T>
void foo(T&&);
//...
const int i=42;
foo(i); // the compiler will defines T = const int &
         //          T&&  = const int & && = const int &
         // => the compiler instantiates void foo<const int &>(const int &);
foo(6*7);// the compiler will defines T = int
         //          T&&  = int &&
         // the compiler instantiates  void foo<int>(int &&);

在这种情况下,模板foo的实例化可以产生 一个函数,它通过左值引用或带有参数rvalue引用的函数来获取参数:转发引用也是 rvalue引用或左值引用,具体取决于模板类型推导。它的名字是这样的,因为在这种情况下,参数应该作为左值或x值传递,这是T&& std::forward<T>(T&& a)

的工作。

如果声明一个函数有:

 template<class T>
 void foo(ATemplateClass<T> && a);
无论编译器为T推导出什么类型,你都会得到一个右值参考参数。