【发布时间】:2022-01-10 13:44:21
【问题描述】:
给定以下代码sn-p:
struct Foo {
};
struct Bar {
operator const Foo() {
return Foo();
}
};
int main() {
Bar bar;
Foo foo(bar);
return 0;
}
见这里godbolt
使用 gcc 11.2 可以正常编译,但使用 clang 12.0 编译失败并出现以下错误:
<source>:12:13: error: no viable conversion from 'Bar' to 'Foo'
Foo foo(bar);
^~~
<source>:1:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Bar' to 'const Foo &' for 1st argument
struct Foo {
^
<source>:1:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'Bar' to 'Foo &&' for 1st argument
struct Foo {
^
<source>:5:5: note: candidate function
operator const Foo() {
^
<source>:1:8: note: passing argument to parameter here
struct Foo {
^
- 哪个实现是正确的?
- 这实际上是有效的 C++ 吗?
PS:我知道它可以通过删除 const 或返回 const 引用来解决。
【问题讨论】:
-
仅在 GCC、Clang 和 MSVC 之外 Clang 会产生此错误,仅用于直接初始化(不是复制初始化或引用初始化)并且仅在 C++14 或更低模式下。
-
此外,只要为 foo 显式声明了复制构造函数,它就可以很好地编译:godbolt.org/z/fz8KE11ns
-
在 clang 12 上将 C++ 标准更改为 17 及更高版本允许它工作。 gcc.godbolt.org/z/KhGxzo6xs
-
@alagner 声明复制构造函数禁止声明隐式移动构造函数,这是 Clang 似乎试图在构造中使用的。也许这是CWG 2077。
-
这很有趣:godbolt.org/z/YM15T5Gc3 只有在选择 C++11 或 C++14 时才会在 clang 上失败。即使对于 C++03 也很好。
标签: c++ language-lawyer