所以我有这段代码:
struct Foo {
Foo() { cout << "default\n"; }
Foo(const long long) { cout << "implicit\n"; }
};
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)
会使用我的隐式转换然后转换构造函数。 But it errors:
错误:从
Bar
转换为非标量类型Foo
请求
这样可以正常工作:Foo foo(Bar(13))
。为什么我的隐式转换用于显式转换构造,而不用于隐式转换构造?
我从https://en.cppreference.com/w/cpp/language/copy_initialization得到的规则说:
转换的结果,如果使用转换构造函数,则是prvalue表达式,然后用于直接初始化对象
答案 0 :(得分:8)
首先,从Bar
到long long
的隐式转换以及从long long
到Foo
的隐式转换都是用户定义的转换。
Foo foo = Bar(13);
执行copy initialization,编译器会尝试隐式地将Bar
转换为Foo
。需要进行两次隐式转换,即将Bar
转换为long long
,然后将long long
转换为Foo
。但是,在一个implicit conversion序列中只允许一个用户定义的转换。
隐式转换序列按以下顺序组成:
1)零个或一个标准转换序列;
2)零或一个用户定义的转换;
3)零个或一个标准转换序列。
用户定义的转换包含零个或一个非显式单参数构造函数或非显式转换函数调用
Foo foo(Bar(13));
执行direct initialization。将检查Foo
的构造函数,并通过重载决策选择最佳匹配。只需要一次隐式的用户定义转换(从Bar
到long long
);之后调用Foo::Foo(long long)
直接构建foo
。
答案 1 :(得分:2)
当您使用复制初始化时,然后根据documentation
重点是我的。事实并非如此。此外,复制初始化中的隐式转换必须直接从初始化程序生成T,而例如, direct-initialization期望从初始化器到T的构造函数的参数的隐式转换。