从右值参数推导对const的引用
deducing references to const from rvalue arguments
好吧,这个问题可能看起来很傻,但它来了:
template <typename T>
void foo(T& x)
{
}
int main()
{
foo(42);
// error in passing argument 1 of 'void foo(T&) [with T = int]'
}
是什么阻止C++用T = const int
实例化foo
函数模板?
问题是模板类型推导必须计算出精确匹配,在这种特殊情况下,由于签名中的引用,精确匹配需要一个左值。值42不是左值,而是右值,并且用const int
解析T
不会产生完全匹配。由于模板类型的推导仅限于精确匹配,因此不允许进行该推导。
如果不是使用文字,而是使用不可变的左值,那么编译器将适当地推导类型,因为const int
将成为参数的完美匹配:
const int k = 10;
foo( k ); // foo<const int>( const int & ) is a perfect match
现在有一个特殊的规则可以调用一个带有右值的常量引用(非可变左值)的函数,这意味着要创建一个稍后绑定到引用的临时左值,但要使该规则生效,函数必须先有签名,这就是为什么明确声明模板类型为const int
有效的原因:foo<const int>(42)
。
这就是规则;-)。如果让编译器从参数中推导类型,它会选择最简单的方法。
在我看来,这并不是不合理的。你的模板说它需要一个非常量引用,所以它不使用右值编译。
您可以在调用站点告诉它您的意思:foo<int const>(42);
,或者更改模板以明确它不需要可变引用:template <typename T> void foo(T const & x) { }
。
在C++11中,您可以有更多的选项来表达您的模板将接受和不接受的内容。
无论是模板函数还是普通函数,右值都不能通过引用传递。(所以const T&
有效,但T&
无效)。
What is preventing C++ to instantiate the foo function template with T = const int instead?
假设C++允许并生成T = const int
。现在过了一段时间你把foo改成
template<typename T>
void foo (T& x)
{
x = 0;
}
现在编译器必须生成错误。对于最终用户来说,这种体验将是奇怪的,因为对于像x = 0;
这样的有效语句,它开始给出错误。这可能就是为什么编译器在第一阶段阻止自己的原因!
- 将const引用参数初始化为默认参数会导致悬空引用吗
- 为什么当我为 for(auto& it : myUnorderedMap) {... = std::move(it.second)} 时,我会得到一个 const 引用?
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- 如何在构造函数中传递 const 引用时强制编译器不接受右值
- 为什么我需要三个嵌套的大括号来调用赋值运算符,将const引用到二维数组
- 对临时对象的Const引用不会延长其生存期
- 对 const 引用参数使用默认值会导致崩溃
- 在运算符重载中使用带有 const 引用的 friend 函数
- C++通过 const 引用传递时不调用派生类函数
- 具有字符串文本构造函数的类不适用于 const 引用初始化
- 为什么要返回对小类成员的 const 引用?
- C - 最好将枚举类作为值或const引用
- RVO:返回由值传递的值,即使显式分配给 const 引用也是如此
- const引用与可变成员的对象
- 每当传递lvalue时,每当通过rvalue传递时,将const引用存储
- 对类成员而不是 getter 的 Const 引用
- 从类型 'Matrix&' 的右值初始化 类型的非 const 引用无效 'Matrix'
- 在函数中使用 const 引用参数访问函数中成员的最佳实践 C++.
- STD ::配对的const引用如何工作
- 为什么我的C 函数拒绝返回const引用