vso*_*tco 25 c++ copy-constructor language-lawyer uniform-initialization c++11
显式复制构造函数不允许使用类似的东西Foo foo = bar;,并强制执行复制用法Foo foo(bar);.此外,显式复制构造函数还禁止通过函数的值返回对象.但是,我尝试用大括号替换副本初始化,就像这样
struct Foo
{
Foo() = default;
explicit Foo(const Foo&) = default;
};
int main()
{
Foo bar;
Foo foo{bar}; // error here
}
Run Code Online (Sandbox Code Playgroud)
我收到了错误(g ++ 5.2)
错误:没有匹配函数来调用'Foo :: Foo(Foo&)'
或(clang ++)
错误:struct initializer中的多余元素
删除explicit使得代码在g ++下可编译,clang ++仍然失败并出现相同的错误(感谢@Steephen).这里发生了什么?统一初始化是否被视为初始化列表构造函数(胜过所有其他构建函数)?但如果是这种情况,为什么程序在复制构造函数非显式时编译?
bog*_*dan 24
在C++ 14最终确定之后,您遇到了一个由Core issue 1467的解决方案解决的案例.
让我们首先注意,类foo是一个聚合.您的代码是做直接列表初始化的foo.列表初始化的规则在[8.5.4p3]中.
在C++ 14中(引自N4140,最接近公布标准的工作草案),上面的段落开始于:
对象或类型引用的列表初始化
T定义如下:
- 如果
T是聚合,则执行聚合初始化(8.5.1).[...]
因此,如果您的类是聚合,则编译器会尝试进行聚合初始化,但这会失败.
这被认为是一个问题,并在工作草案中得到修复.从当前版本N4527引用,上述段落现在开头:
对象或类型引用的列表初始化
T定义如下:
- 如果
T是类类型且初始化列表具有cv 类型的单个元素U,其中UisT或派生自的类T,则从该元素初始化对象(通过复制初始化进行复制列表初始化,或通过直接初始化直接列表初始化).- 否则,如果
T是字符数组且初始化列表具有单个元素,该元素是适当类型的字符串文字(8.5.2),则按照该部分中的描述执行初始化.- 否则,如果
T是聚合,则执行聚合初始化(8.5.1).[...]
你比如现在落在通过第一点所描述的情况中,并且foo是直接列表初始化使用默认的拷贝构造函数(无论它是explicit,因为它是直接初始化).
那就是......如果编译器在缺陷报告中实现了解决方案.
explicit.explicit无关紧要).bar- 看起来像IntelliSense使用的EDG编译器也没有更新).更新:由于这个答案是写的,工作草案已经通过几个与问题中的例子和上面的解释相关的方式进一步修改:
- 如果
T是聚合类和[...]
explicit这并没有改变以下事实:在实施所有更改之后,问题中的示例旨在工作,有或没有explicit; 值得了解的是,使其发挥作用的潜在机制略有改变.
请注意,所有这些更改都是缺陷报告的解决方案,因此当编译器处于C++ 14和C++ 11模式时,它们应该适用.
| 归档时间: |
|
| 查看次数: |
1340 次 |
| 最近记录: |