三元允许隐式调用显式复制构造函数吗?
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++ 实现无法接受您编写的条件表达式的格式正确。
考虑以下代码:
#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++ 实现无法接受您编写的条件表达式的格式正确。