C ++:模板函数,显式指定引用类型作为类型参数

时间:2014-12-02 18:34:32

标签: c++ function-templates

我正在玩C ++模板类型演绎并设法编译这个小程序。

template<typename T>
 void f(const T& val)
 {
   val = 1;
 }


 int main()
 {
    int i = 0;
    f<int&>(i);
 }

它编译所有主要的编译器,但我不明白为什么。当f明确标记为val时,为什么val可以分配给const?它是这些编译器中的错误还是根据C ++标准的有效行为?

3 个答案:

答案 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类型,因此当Tint &时,const将适用引用类型本身(无论如何引用都是不可变的,这是无意义的),而不是引用的类型。这就是参考折叠规范忽略TR上的任何cv限定符的原因。


* 模板类型参数是 typedef-name ,根据§14.1[temp.param] / p3:

  

type-parameter ,其标识符不遵循省略号   将其标识符定义为 typedef-name (如果使用   classtypename)或模板名称(如果声明为   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}}类型的东西。