当T是一个引用类型时,为什么const T&参数中的const会消失?

7
以下代码表明,如果一个模板带有一个引用类型(例如int&)的 ref-to-const 参数被实例化,那么该参数不是 const
#include <iostream>

template<typename T>
void f(const T& arg)         // arg isn't const if T is a reference type
{
  arg = -1;
}

int main()
{
  int x = 0;
  f<int&>(x);                // instantiate f with reference type
  std::cout << x << '\n';    // prints -1 under gcc, clang, and msvc
}

这里发生了什么?
我猜测最初arg的类型是int & const &,然后以某种方式转变为int&。如果是这样,按照标准如何进行转换?如果不是这样,那是什么情况呢?

1
关于c98-03-reference-collapsing-and-cv-qualifiers的相关内容。 - Jarod42
http://www-01.ibm.com/support/knowledgecenter/SS2LWA_12.1.0/com.ibm.xlcpp121.bg.doc/language_ref/reference_collapsing.html有两个关于引用折叠的表格。 - Jarod42
相关/重复问题:如何实现引用折叠? - dyp
https://dev59.com/EIXca4cB1Zd3GeqPMLO2#27256623 - T.C.
2个回答

4
感谢Vlad from MoscowC++: template function with explicitly specified reference type as type parameter的答案,我相信这种const消失的关键是[dcl.ref],其中说:

在声明了T DD具有以下形式之一的情况下

& attribute-specifier-seqopt D1
&& attribute-specifier-seqopt D1

并且声明中标识符D1的类型是“derived-declarator-type-list T”,则标识符D的类型为“derived-declarator-type-list引用T”。可选的attribute-specifier-seq适用于引用类型。除非通过typedef-name([dcl.typedef],[temp.param])或decltype-specifier([dcl.type.simple])引入cv-qualifiers,否则cv-qualified引用是不合法的,在这种情况下忽略cv-qualifiers.

我已经加粗了相关文本。(我想将整个段落的格式设置为标准格式,但我无法弄清楚如何得到正确的缩进和添加下标。)
一旦const消失,正常的引用折叠就像往常一样进行。

这似乎是正确的答案。请注意,在https://dev59.com/B27Xa4cB1Zd3GeqPnTYF#14761809中,Yakk从8.3.2/5(在C++11的预发布版本中曾经是14.3.2/4)中推导出来。 - jogojapan

3

const T 是一种类型为 T 的对象,其值无法被修改。但是,当 T 是一个引用类型时,const 修饰符是多余的,因为一旦初始化,引用就不能被改变 - 它们总是指向相同的对象。因此,当 T=int& 时,const T 只是一个 T(在这种情况下是 int&)。因此,f<int&> 接受的参数是一个左值引用到一个 int&,根据 c++11 的折叠规则,它只是一个 int&


1
你能否提供一些指导,告诉我在标准中这种行为是在哪里规定的?也就是说,当T是引用类型时,const T就是T。 - KnowItAllWannabe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接