ava*_*kar 27 c++ language-lawyer overload-resolution c++17
考虑以下代码。
struct any
{
template <typename T>
operator T &&() const;
template <typename T>
operator T &() const;
};
int main()
{
int a = any{};
}
Run Code Online (Sandbox Code Playgroud)
这里第二个转换运算符由重载决议选择。为什么?
据我了解,这两个运算符分别推导为operator int &&() const和operator int &() const。两者都在可行的功能集中。通读 [over.match.best] 并没有帮助我弄清楚为什么后者更好。
为什么后者的功能比前者好?
Bri*_*ian 13
T&首选返回的转换运算符,因为它比返回的转换运算符更专业T&&。
参见 C++17 [temp.deduct.partial]/(3.2):
在调用转换函数的上下文中,使用转换函数模板的返回类型。
和/9:
如果,对于给定类型,扣除在两个方向成功(即,类型是上述变换后相同的)和二者
P并A分别引用类型(与类型被替换之前上文提及): -如果从参数模板的类型是左值引用而参数模板中的类型不是,参数类型不被认为至少与参数类型一样特殊;...
Yak*_*ont 12
推导出来的返回值转换运算符有点奇怪。但核心思想是它就像一个函数参数来选择使用哪个。
之间作出决定时T&&,并T&在T&在重载决策规则的胜利。这是为了允许:
template<class T>
void f( T&& ) { std::cout << "rvalue"; }
template<class T>
void f( T& ) { std::cout << "lvalue"; }
Run Code Online (Sandbox Code Playgroud)
上班。 T&&可以匹配左值,但是当左值和通用引用重载都可用时,首选左值。
正确的转换运算符集可能是:
template <typename T>
operator T&&() &&;
template <typename T>
operator T &() const; // maybe &
Run Code Online (Sandbox Code Playgroud)
甚至
template <typename T>
operator T() &&;
template <typename T>
operator T &() const; // maybe &
Run Code Online (Sandbox Code Playgroud)
以防止失败的终身延长咬你。
3 用于确定排序的类型取决于完成偏序的上下文:
[剪辑]
(3.2) 在调用转换函数的上下文中,使用转换函数模板的返回类型。
然后在选择重载时最终取决于“更专业”的规则:
(9.1) 如果参数模板中的类型是左值引用而参数模板中的类型不是,则认为参数类型至少不像参数类型那样特殊;除此以外,
因此operator T&&至少不如 专门化operator T&,同时没有规则状态operator T&至少不如 专门化operator T&&,因此operator T&比 更专门化operator T&&。
在其他条件相同的情况下,更专业的模板胜过更少的重载解决方案。