三元允许隐式调用显式副本构造函数?

时间:2018-10-09 11:38:46

标签: c++ gcc compiler-bug

考虑以下代码:

#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,它们的行为都相同。 >

1 个答案:

答案 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 ++的实现不能接受您编写的格式正确的条件表达式。