为什么我不能将C ++通用引用与标准引用混合使用?

时间:2016-01-16 23:41:27

标签: c++ c++11

我试图了解C ++ 11的通用引用,并编写了以下代码:

#include <cstdio>                                                                                                                                                                                                                                            

template <typename L, typename R>                                                                                                                                                                                                                            
static void Run(L&& lhs, const R& rhs) {                                                                                                                                                                                                                     
  lhs += rhs;                                                                                                                                                                                                                                                
}                                                                                                                                                                                                                                                            

static void Run2(int&& lhs, const int& rhs) {                                                                                                                                                                                                                
  lhs += rhs;                                                                                                                                                                                                                                                
}                                                                                                                                                                                                                                                            

int main() {                                                                                                                                                                                                                                                 
  int a = 0;                                                                                                                                                                                                                                                 
  int b = 3;                                                                                                                                                                                                                                                 
  Run(a, b);                                                                                                                                                                                                                                                 
  printf("%d\n", a);                                                                                                                                                                                                                                         
  // This does not compile.                                                                                                                                                                                                                                  
  Run2(a, b);                                                                                                                                                                                                                                                
  printf("%d\n", a);                                                                                                                                                                                                                                         
  return 0;                                                                                                                                                                                                                                                  
}

请注意Run()有效,但调用Run2()的行无法编译。我无法弄清楚原因。我得到的错误是no known conversion from 'int' to 'int &&' for 1st argument

我确定编译器是正确的,但我无法弄清楚原因。似乎Run()Run2()正在做同样的事情吗?

顺便说一句,将Run2()更改为使用单个参数进行模板化也不起作用。

4 个答案:

答案 0 :(得分:5)

“通用引用”只能在推断引用类型的上下文中发生,例如在模板类型上下文T&&中。在这种情况下,对于rvalue参数,T可以推导为int,因此您可以使用int&&作为参数类型;或者作为您的左值参数的int&,这将为每个参考折叠规则的类型int& &&变为int&。在Run2函数中,类型直接为int&&,因此除非使用std::move,否则它不能绑定到任何左值。

答案 1 :(得分:2)

Rvalue引用无法绑定到左值。

创建转发引用的特殊规则是,推导出的模板参数T在函数参数T = U&中出现时可以推导为T&&,这使得函数参数类型为U&(感谢来自U& &&的参考资料崩溃)。但是,Run2的参数类型不是推导出来的,因此第一个参数直接是右值参考。

使用单个模板参数将Run2更改为函数模板意味着参数推导将失败,因为没有适合两个参数的一致类型集。

答案 2 :(得分:1)

第一个是通用引用(如Scott Meyers Effective Modern C++一书中所述),第二个是右值引用

为了使其正常工作,您需要像这样调用它:

Run2(std::move(a), b); 

答案 3 :(得分:1)

Run(a,b) 调用一个函数,其中typename L == int&amp;和R == int

所以 static void Run(L&& lhs, const R& hrs)

是模板实例化为

static void Run(int & && lhs, const int& hrs)

或实际因为参考折叠,它变成

static void Run(int& lhs, const int& hrs)

Run2需要lhs的右值引用,它只能从转换中获得或者被赋予一个未命名的变量(临时)。在你的情况下,你可以使用演员来调用函数:

Run(std::move(a), b)