我正在玩C ++模板类型演绎并设法编译这个小程序。
template<typename T>
void f(const T& val)
{
val = 1;
}
int main()
{
int i = 0;
f<int&>(i);
}
它编译所有主要的编译器,但我不明白为什么。当f
明确标记为val
时,为什么val
可以分配给const
?它是这些编译器中的错误还是根据C ++标准的有效行为?
答案 0 :(得分:4)
§8.3.2[dcl.ref] / p6:
如果 typedef-name (7.1.3,14.1) * 或 decltype-specifier (7.1.6.2) 表示类型TR,它是对类型T的引用,是对类型的引用 创建类型“对cv TR的左值引用”创建类型“左值” 引用T“,同时尝试创建”rvalue引用类型 到cv TR“创建TR类型。
这称为引用折叠,并在C ++ 11中引入。在C ++ 03中,您的代码格式不正确,但有些编译器支持它作为扩展。
请注意,在const T &
中,const
适用于T
类型,因此当T
为int &
时,const
将适用引用类型本身(无论如何引用都是不可变的,这是无意义的),而不是引用的类型。这就是参考折叠规范忽略TR
上的任何cv限定符的原因。
* 模板类型参数是 typedef-name ,根据§14.1[temp.param] / p3:
type-parameter ,其标识符不遵循省略号 将其标识符定义为 typedef-name (如果使用
class
或typename
)或模板名称(如果声明为template
)在模板声明的范围内。
答案 1 :(得分:3)
我想在C ++标准(8.3.2参考文献)中添加以下引用的其他帖子
1 ...除非通过使用typedef-name引入cv限定符,否则Cv限定的引用是不正确的(7.1.3, 14.1)或decltype-specificer(7.1.6.2),在这种情况下忽略 cv-qualifiers。
[ Example:
typedef int& A;
const A aref = 3; // ill-formed; lvalue reference to non-const initialized with rvalue
在上面C ++标准的例子中,最后一个语句不会被编译,因为忽略了限定符const(根据引用),你可能不会将rvalue与非const引用绑定。
答案 2 :(得分:1)
const T&
不会变为int&
:在f<int&>(i)
中,您明确将T
设置为int&
。当const
的定义用于确定T
的类型时,val
仅输入图片,const int&
的类型变为&
(在此替换过程中,引用被折叠的一个微妙之处,所以你最终不能使用两种{{1}}类型的东西。