考虑以下代码:
#include <cstdio>
struct A
{
A(){}
explicit A(const A&) {std::puts("copy");}
};
int main()
{
A a;
true ? a : A();
return 0;
}
据我所知,三元会尝试复制 a ,并且由于复制构造函数是显式的,因此应该会失败,但是gcc可以很好地编译并创建一个副本。 Clang发出了预期的错误。
这是gcc中的错误吗?
我在c ++ 17模式下使用的是gcc 8.1和clang 7.0,但我也在{++ 3}的c ++ 98模式下尝试了所有版本的gcc,它们的行为都相同。 >
答案 0 :(得分:6)
Clang拒绝它是正确的,这确实是一个GCC错误。为了简单起见,我将引用n4659(必须是C ++ 17标准的最近文档)。
首先,由[expr.cond] ¶6指定的示例中条件表达式的类型必须为A
类型的prvalue。
现在,根据[expr.cond] ¶7,我的重点是:
左值到右值,数组到指针和函数到指针标准 转换是在第二和第三操作数上进行的。
a
必须能够进行从左值到右值的转换。 [conv.lval] ¶3.2中的a
的哪一个(同样是强调我的)指定为
否则,如果T具有类类型,则转换 copy-initializes glvalue的结果对象。
在任何情况下,从A
复制A
的初始化都应选择重载分辨率([over.match.copy] ¶1.1)中的转换构造函数:
T的转换构造函数是候选函数。
显式副本构造函数不是转换构造函数([class.conv.ctor] ¶3)
非显式复制/移动构造函数([class.copy])是转换构造函数。
符合C ++的实现不能接受您编写的格式正确的条件表达式。