为什么不对转换构造函数进行隐式强制转换?

Why Doesn't This Do an Implicit Cast to the Converting Constructor?

本文关键字:转换 构造函数 为什么不      更新时间:2023-10-16

所以我有这个代码:

struct Foo {
Foo() { cout << "defaultn"; }
Foo(const long long) { cout << "implicitn"; }
};
struct Bar {
Bar(const short param) : param(param) {}
operator long long() const { return static_cast<long long>(param); }
const short param;
};

我本以为Foo foo = Bar(13)会使用我的隐式强制转换,然后使用转换构造函数。但它错误:

错误:请求从Bar转换为非标量类型Foo

不过这工作正常:Foo foo(Bar(13)).为什么我的隐式转换用于显式转换构造,而不用于隐式转换构造?

我从 https://en.cppreference.com/w/cpp/language/copy_initialization 那里得到的规则是:

转换的结果(如果使用转换构造函数,则为 prvalue 表达式(随后用于直接初始化对象

首先,从Barlong long的隐式转换,以及从long longFoo的隐式转换都是用户定义的转换。

Foo foo = Bar(13);执行副本初始化,编译器将尝试将Bar转换为隐式Foo。需要两个隐式转换,即将Bar转换为long long然后将long long转换为Foo。但在一个隐式转换序列中只允许一个用户定义的转换。

隐式转换序列按以下顺序由以下内容组成:

1(零个或一个标准转换序列;

2(零个或一个用户定义的转换;

3(零个或一个标准转换序列。

用户定义的转换由零个或一个非显式单参数构造函数或非显式转换函数调用组成

Foo foo(Bar(13));执行直接初始化。将检查Foo的构造函数,并通过重载解析选择最佳匹配。只需要一个隐式用户定义的转换(从Barlong long(;之后,Foo::Foo(long long)被调用直接构造foo

当您使用副本初始化时,根据文档

此外,复制初始化中的隐式转换必须直接从初始值设定项生成 T,而直接初始化需要从初始值设定项到 T 构造函数参数的隐式转换。

重点是我的。事实并非如此。