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

Why can't I mix C++ universal references with standard reference?

本文关键字:参考 标准 混合 C++ 为什么 不能      更新时间:2023-10-16

我试图理解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("%dn", a);                                                                                                                                                                                                                                         
  // This does not compile.                                                                                                                                                                                                                                  
  Run2(a, b);                                                                                                                                                                                                                                                
  printf("%dn", a);                                                                                                                                                                                                                                         
  return 0;                                                                                                                                                                                                                                                  
}

请注意,Run()有效,但调用Run2()的行将无法编译。 我真的想不通为什么。 我得到的错误是no known conversion from 'int' to 'int &&' for 1st argument.

我确定编译器是对的,但我无法弄清楚为什么。 这似乎很Run()Run2()正在做同样的事情,对吗?

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

"

通用引用"只能在推导引用类型的上下文中发生,例如在模板类型上下文T&&中。在这种情况下,可以将 T 推导出为右值参数的int,因此int&&作为参数类型;或者作为您的 lvalue 参数的int&,这将给出每个引用折叠规则变得只是int&的类型int& &&。在 Run2 函数中,类型是直接int&&的,因此除非使用 std::move,否则它无法绑定到任何 lvalue。

右值引用不能绑定到左值。

创建转发引用的特殊规则是,当推导的模板参数T出现在函数参数T&&中时,它可以推导出为T = U&,这使得函数参数类型U&(由于引用从U& &&折叠)。但是,没有推导Run2参数的类型,因此第一个参数直接是右值引用。

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

第一个是通用参考(如斯科特·迈耶斯(Scott Meyers)有效现代C++一书中所描述的那样),第二个是右值参考

为了使它工作,你需要这样称呼它:

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

Run(a,b)调用一个函数,其中类型名 L==int& 和 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)