C++ 允许隐式调用显式复制构造函数吗?

C++ 允许隐式调用显式复制构造函数吗?,c++,gcc,compiler-bug,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 { A(){} 显式A(常数A&){std::put(“copy”);} }; int main() { A A; 是吗?a:a(); 返回0; }

考虑以下代码:

#include <cstdio>
struct A
{
    A(){}
    explicit A(const A&) {std::puts("copy");}
};

int main() 
{
    A a;
    true ? a : A();
    return 0;
}
#包括
结构A
{
A(){}
显式A(常数A&){std::put(“copy”);}
};
int main()
{
A A;
是吗?a:a();
返回0;
}
据我所知,三元函数将尝试复制a,并且应该失败,因为复制构造函数是显式的,但是gcc编译得很好,并创建了一个副本。叮当声像预期的那样吐出一个错误

这是gcc中的错误吗


我在c++17模式下使用gcc 8.1和clang 7.0,但我也在c++98模式下尝试了gcc的所有版本,它们的行为都是一样的。

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

首先,您的示例中的条件表达式的类型(由指定)必须是
a
类型的prvalue

现在,根据我的观点:

左值到右值、数组到指针、函数到指针标准 对第二个和第三个操作数执行转换

a
必须能够进行左值到右值的转换。对于
a
,在(同样强调我的)中指定为

否则,如果T具有类类型,则转换复制将初始化 从glvalue生成结果对象

A
复制
A
的初始化,在任何上下文中,都应该在重载解析()中选择一个转换构造函数:

T的转换构造函数是候选函数

并且显式复制构造函数不是转换构造函数()

非显式的复制/移动构造函数([class.copy])是一个转换构造函数


一个一致的C++实现,不能接受你所写的条件表达式。

是一个带有该代码的GooBoad链接。(你可以通过点击“共享”按钮得到一个。)Clang拒绝它,而gcc接受它。为什么三元复制参数?表达式的结果将被丢弃。三元运算符的求值通常可能会导致将任一参数转换为公共类型,但这里的公共类型是
a
,因此不需要转换。@MSalters-是否丢弃,它必须格式正确。表达式的结果是一个右值,这意味着在
a
上必须可以进行左值到右值的转换。@StoryTeller:不一定不同意您的观点(我必须检查Standardese),但这些转换并非在所有情况下都会发生。例如,您有
sizeof(true?a:a())