当同样好的转换函数可用时,为什么重载决议更喜欢移动构造函数而不是非特殊构造函数?
Why does overload resolution prefer a move constructor over a non-special constructor when equally good conversion functions are available?
以下程序:
#include <iostream>
struct A
{
A() { std::cout << "A()\n"; }
A(int) { std::cout << "A(int)\n"; }
};
struct C {
operator int() {
std::cout << "operator int\n";
return 42;
}
operator A() {
std::cout << "operator A\n";
return A();
}
};
int main() {
auto a = A{C{}};
};
编译并在 运行 时打印:
operator A
A()
这表明选择了 A
的移动构造函数来执行初始化,调用 C::operator A()
将 C
转换为移动构造函数期望的类型。
或者,可以选择 A::A(int)
构造函数,并调用 C::operator int()
。但是 A::A(int)
显然失去了重载解析。
为什么会这样?我无法在标准中看到任何规则来解释为什么 A
的移动构造函数赢得重载决议。
(这个问题的灵感来自 ;我不明白为什么那个答案中的代码有效。)
似乎 GCC 和 Clang 都通过在初始化 [=21] 类型的对象时直接考虑将 cv T 的转换函数作为候选来实现对 CWG2327 的修复=]cv2T,除了构造函数.
当C::operator A()
本身被视为候选者时,它是完全匹配,因此优先于需要用户定义转换的构造函数调用。
该问题仍处于起草状态,因此您不会在措辞中找到它。
值得注意的是,两者都拒绝 -std=c++14
。
以下程序:
#include <iostream>
struct A
{
A() { std::cout << "A()\n"; }
A(int) { std::cout << "A(int)\n"; }
};
struct C {
operator int() {
std::cout << "operator int\n";
return 42;
}
operator A() {
std::cout << "operator A\n";
return A();
}
};
int main() {
auto a = A{C{}};
};
编译并在 运行 时打印:
operator A
A()
这表明选择了 A
的移动构造函数来执行初始化,调用 C::operator A()
将 C
转换为移动构造函数期望的类型。
或者,可以选择 A::A(int)
构造函数,并调用 C::operator int()
。但是 A::A(int)
显然失去了重载解析。
为什么会这样?我无法在标准中看到任何规则来解释为什么 A
的移动构造函数赢得重载决议。
(这个问题的灵感来自
似乎 GCC 和 Clang 都通过在初始化 [=21] 类型的对象时直接考虑将 cv T 的转换函数作为候选来实现对 CWG2327 的修复=]cv2T,除了构造函数.
当C::operator A()
本身被视为候选者时,它是完全匹配,因此优先于需要用户定义转换的构造函数调用。
该问题仍处于起草状态,因此您不会在措辞中找到它。
值得注意的是,两者都拒绝 -std=c++14
。