为什么我不能C++通用参考与标准参考混合使用?
Why can't I mix C++ universal references with standard reference?
我试图理解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)
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- C++错误消息*成员参考.**初学者*
- 编译标准库类型
- 标准::enable_if和通用参考的使用差异
- 标准::积累参考?
- 如何理解 C++17 标准参考中的 [intro.object]/3? N4659 的
- 标准库中的任何正则表达式语法是否支持 (?(定义)用于子模式参考?
- C 标准:通过复制返回以初始化无RVO的参考:是否有任何副本
- 是参考转换是标准转换
- 我怎样才能打破这个标准::shared_ptr参考循环
- C++11:模板专用化的 constexpr 成员的标准参考需要额外声明
- 为什么我不能C++通用参考与标准参考混合使用?
- C++11 gcc:声明中的显式限定?标准参考号
- 通用参考的标准/官方名称是什么?
- 在标准中使用 8.5.3p4,如何确定 T 与 T&的参考兼容?
- c++标准布局和参考
- C++14/1y: "operator+ must take either one or two arguments"的标准参考 ?
- 我们可以将规范性参考文献中未明确引用的内容应用到C++标准中吗