使用统一初始化构造对象的简单程序编译失败
Simple program using uniform initialization to construct an object fails to compile
考虑以下程序:
struct X
{
X(int, int) { }
X(X&&) { }
};
int main()
{
X x( {0, 1} ); // Doesn't compile on ICC 13.0.1, compiles on
// Clang 3.2, GCC 4.7.2, and GCC 4.8.0 beta.
}
当使用GCC 4.7.2, GCC 4.8.0和Clang 3.2编译时,该程序执行以下操作(*):
- 构造一个
X
类型的临时变量,将值0
和1
传递给构造函数,则; - 移动
X
从临时构建。
对于ICC 13.0.1,它不编译。
问题1:谁是对的?
(*) 实际上,省略了临时变量的创建和对move构造函数的调用,但是使用-fno-elide-constructors
选项编译并向构造函数添加一些打印输出显示了正在发生的事情。
现在考虑上面程序的以下细微变化,其中使用统一初始化直接初始化x
:
int main()
{
X x{ {0, 1} }; // ERROR! Doesn't compile.
// ^........^
}
我不希望用大括号代替括号来改变这里的任何东西,但它确实改变了:这个程序不能在我测试过的任何编译器上编译(Clang 3.2, GCC 4.7.2, GCC 4.8.0 beta和ICC 13.0.1)。
问题2:为什么?
这只是所有编译器中的一个bug。§8.5.4/3说,
类型T的对象或引用的列表初始化定义如下:
—如果初始化列表没有元素,并且T是带有默认构造函数的类类型,则对象为初始化值。
—否则,如果T是聚合,则执行聚合初始化(8.5.1)。
-否则,如果T是std::initializer_list的专门化,则按如下所述构造initializer_list对象并用于初始化该对象…
—否则,如果T是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载解析选择最佳构造函数(13.3,13.3.1.7)。如果需要窄化转换(见下文)来转换任何参数,则程序是病态的。
—否则,如果T是引用类型,则T引用的类型的右值临时值被列表初始化,并且引用被绑定到该临时类型。
—否则,如果初始化列表只有一个元素,则从该元素初始化对象或引用;如果需要缩窄转换(见下文)来将元素转换为T,则程序是病态的。
…
有相当多的案例。请注意,您实际上是在列表初始化一个绑定到右值引用的右值临时对象。
对于GCC,我认为它正在尝试应用上面提到的最后一项,用于单元素初始化列表。如果我将构造函数签名更改为X(X&&, int = 3)
,则初始化器{ {0, 1} }
失败,但{ {0, 1}, 3 }
成功。单个项目应该成功,因为元素是一个大括号初始化列表,我相信case应该允许额外的大括号,类似于双亲。但是这种失败与使用大括号省略的GCC的其他缺点相似。
我的高级印象是,当编译器试图将列表视为具有类型的对象时,问题就出现了,而它不是。很难将其转换回圆括号式参数列表。
更具体地查看错误消息(感谢LWS链接),
-
ICC坚持需要一个表达式。这是错误的,因为根据基本语法,大括号初始化列表可以包含其他大括号初始化列表,而不仅仅是表达式。
-
Clang说"候选构造函数不可行:不能将初始化列表参数转换为'X'"但如果转换是显式的,使用
X x{ X{0, 0 } };
,它可以工作。这说不通啊。这不是转换,因为列表没有可转换的类型。list-initialization。 -
GCC说"没有已知的参数1从"到'X&&'的转换"表明它甚至没有定义一个临时变量来绑定到引用。与Clang一样,它似乎在尝试虚假的转换,并指定
X{0,0}
修复它。
- GDB 8.1 无法在单线程简单程序中跟踪 std::string 变量的值
- 令牌之前的简单程序预期标识符'('
- 带有类和链表的简单C++程序
- 引发未经处理的异常:简单 C++ 程序中的读取访问冲突,动态增加数组长度以存储数字
- C++链表简单程序崩溃
- 简单程序中的意外推力错误
- 未经GCC优化而编译的简单C++程序不会产生预期的结果
- 运行简单 c++ 程序时出现权限被拒绝错误
- 为什么我的简单C++程序使用队列和 fstream 错误到无效指针
- QT创建者:简单程序未解决的外部符号和外部符号错误
- 在VS2017上调试简单程序时访问冲突(RtlActivateActivationContextUnsafeFast)
- 无法为简单程序运行 docker 容器
- 布尔程序返回错误,即使应该是正确的.简单程序
- C++:帮助解释简单程序的行为
- 在使用小数的简单c++程序中遇到问题
- 简单程序的输入/输出问题
- 我在C中简单程序中的内存故障
- 简单程序没有输出和崩溃.我的解决方案有什么问题
- 简单C++程序上的多个未声明标识符
- C++,Visual Studio 2012和错误4700,用于简单程序中的类变量