Kar*_*yan 18 c++ conversion-operator language-lawyer c++14 c++17
我正在玩下面的代码。
#include <iostream>
struct To
{
To() = default;
To(const struct From&) {std::cout << "Constructor called\n";}
To(const To&) {std::cout << "Copy constructor called\n";}
};
struct From
{
operator To(){std::cout << "Conversion called\n"; return To();}
};
int main()
{
From f;
To t(f);
To t1 = f;
To t2{To(f)};
}
Run Code Online (Sandbox Code Playgroud)
如果我-std=c++14同时使用GCC和Clang同意以下输出。
Constructor called
Conversion called
Constructor called
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用 进行编译-std=c++17,则两个编译器都同意
Conversion called
Conversion called
Conversion called
Run Code Online (Sandbox Code Playgroud)
我知道将几个预期的输出行减少为输出 3 行是由于复制省略,但我无法弄清楚 C++17 中发生了什么变化导致了此输出。究竟是什么标准的变化引发了这种情况?
Bri*_*ian 11
在所有版本的 C++ 中,类类型对象的直接初始化都会在类的构造函数之间执行重载决策;例如,请参见当前草案中的 [dcl.init.general]/16.6.2。有一些例外,但它们不适用于此处。需要注意的是,转换函数不是初始化的候选函数,因此编译器必须选择是否使用To::To(const To&)或To::To(const From&)用于初始化。后者赢得了重载解析,因为参数类型与实参类型完全匹配。
有趣的是,如果To::To(const From&)不存在,那么To::To(const To&)将被调用,并且From将调用对象的转换函数以初始化const To&参数。这不太好,因为它会强制进行复制;由于From::operator To直接创建To对象,因此最好From::operator To直接初始化初始化的目标,而不是创建必须复制到目标的临时对象。不幸的是,当前的标准要求进行复制。这是CWG2327的主题。
委员会尚未决定如何解决 CWG2327,但 Clang 和 GCC 各自对其重载解析规则进行了不同的调整,以便允许在某些情况下删除副本。所以基本上,他们在 C++17 模式下的行为不符合标准,但是是“乐观的”,即实现者希望 CWG2327 的解决方案与他们实现的调整类似。
您可以在此处阅读更多详细信息。本文的更新版本将在下一次邮件中发布,该版本将向 CWG2327 提出正式决议。
| 归档时间: |
|
| 查看次数: |
564 次 |
| 最近记录: |