三元允许隐式调用显式复制构造函数吗?

Ternary allowed to call an explicit copy constructor implicitly?

考虑以下代码:

#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,但我也在 c++98 模式下 compiler explorer 中尝试了所有版本的 gcc,它们的行为都相同。

Clang 拒绝它是对的,它确实是一个 GCC 错误。为了简单起见,我将引用 n4659(我必须与 C++17 标准最接近的文档)。

首先,[expr.cond] ¶6 指定的条件表达式的类型必须是 A.

类型的纯右值

现在,根据 [expr.cond] ¶7,强调我的:

Lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the second and third operands.

a 必须能够进行左值到右值的转换。 a 的哪个在 [conv.lval] ¶3.2 中指定(再次强调我的)为

Otherwise, if T has a class type, the conversion copy-initializes the result object from the glvalue.

A 复制 A 的初始化,在任何情况下,都应该在重载决策中选择转换构造函数 ([over.match.copy] ¶1.1):

The converting constructors of T are candidate functions.

并且显式复制构造函数不是转换构造函数([class.conv.ctor] ¶3)

A non-explicit copy/move constructor ([class.copy]) is a converting constructor.

符合标准的 C++ 实现无法接受您编写的条件表达式的格式正确。