为什么我不能在初始化与统一初始化的初始化列表的引用?为什么我不能在初始化与统一初始化的初始化列表的引

2019-05-13 23:06发布

也就是说,为什么这样的:

struct S {};

struct T
{
    T(S& s) : s{s} {}

    S& s;
};

int main()
{
    S s;
    T t{s};
}

给我用GCC 4.7编译器错误:

test.cpp: In constructor 'T::T(S&)':
test.cpp:5:18: error: invalid initialization of non-const reference of type 'S&' from an rvalue of type '<brace-enclosed initializer list>'

为了修正这个错误,我要改变s{s}s(s) 这难道不是打破统一初始化的,呃, 均匀

编辑 :我试着用铛,铛,并接受它,所以也许这是一个错误的GCC?

Answer 1:

是的,它是一个错误 。 这是新的东西,并在工作文件被评为2012年2月( 链接 )。

尼科尔流星锤使得在GCC好点实际上是根据FDIS的符合标准的编译批准的C ++ 11个标准,因为变化的工作文件中之后作出。



Answer 2:

我相信这是在编译器错误。 通过列表初始化参考初始化处理的两个段落是(按n3337):

§8.5.4/ 3

对象或类型T的参考的列表的初始化被定义如下:

  • 否则,如果初始化列表具有式E的单个元件,要么T是不是引用类型或其引用类型是参考相关到E,所述对象或参考是从元件初始化; 如果收缩转换(见下文)是需要的元件至T转换,是形成不良的节目。

  • 否则,如果T是引用类型,prvalue临时被T引用的类型的被列表初始化,并且引用绑定到该临时。 [注意:通常,结合将失败,并且是形成不良的程序如果参考类型是一个左值参照一个非const类型。 - 注完]

编译器似乎将最后一段的时候,应该将第一,作为参考相关的定义为

8.5.3 / 4

给定类型的“CV1 T1”和“T2 CV2”,“CV1 T1”是参考有关“CV2 T2”如果T1是相同的类型T2或T1是一个基类T2的。

在问题的情况下,参考的类型和支撑初始化列表中初始化是完全一样的,这意味着初始化应该是有效的。


在FDIS稿,等效段落有顺序颠倒。 言下之意是,FDIS稿(n3290)并没有让*左值* S的括号列表初始化 。 在另一方面,阅读文本似乎很明显,它是在标准的目的是为n3337的顺序错误

  • 否则,如果T是引用类型,prvalue临时被T引用的类型的被列表初始化,并且引用绑定到该临时。

  • 否则,如果初始化列表具有单个元件,对象或参考是从元件初始化; 如果收缩转换(见下文)是需要的元件至T转换,是形成不良的节目。

该文件中的命令意味着,因为所有引用类型由第一条处理,提的是在下面的段落参考将毫无意义。



Answer 3:

(注:我在写这个答案为2年后见之明,因为原来的问题的利益;并把从一些评论的信息为实际的答案,使其可搜索)。


当然,初始化类型的参考S&与也类型的参考S&假定直接结合。

问题是在C ++ 11标准的缺陷和由寻址DR1288 。 校正后的文本出现在C ++ 14。

委员会澄清,纠正后的文本是否为预期的C ++ 11,并因此“符合标准的编译”应该实施修正版本。

克++ 4.8跟着C ++ 11标准的公布文本; 然而一旦这个问题曝光后,克++ 4.9实施修正版本,即使-std=c++11开关。

请注意,这个问题并不局限于任何构造函数初始化列表,如: S s; S &t{s}; S s; S &t{s}; 以g ++ 4.8不起作用,也不S s; S &t = s; S &u { t }; S s; S &t = s; S &u { t };



文章来源: Why can't I initialize a reference in an initializer list with uniform initialization?