用户定义的隐式转换操作符和重载解析
User-defined implicit conversion operator and overload resolution
今天我在用户定义的隐式转换操作符中遇到了一个有趣的行为。
让我们看看这段代码:
struct Widget {
Widget(uint64_t) {
}
Widget(const std::string &) {
}
operator uint64_t() {
return static_cast<uint64_t>(123456789UL);
}
operator std::string() {
return std::string("Hello");
}
};
一个基本结构体,可以隐式转换为uint64_t或std::string。
现在,尝试通过std::cout:
打印出一个Widget实例#include <iostream>
int main() {
using std::cout;
Widget w(123456);
cout << w;
}
不管什么原因,Widget总是会被转换成uint64_t类型。首先,我希望调用是有歧义的,并通过标准的显式转换来限定为compile:
int main() {
using std::cout;
Widget w(123456);
cout << static_cast<uint64_t>(w);
}
但由于某种原因,我现在忽略了,操作符uint64_t被选中。我试着去看c++规范,但找不到任何有用的东西来回答我的问题。
谁能帮我弄清楚编译器在做什么重载解析?
优先选择uint64_t
转换。原因很简单,<<
被重载为strings
(basic_strings)的模板。在重载解析上,编译器总是倾向于精确匹配而不是模板。
当然你可以在c++规范中找到它。
读取 §13.3.1/2
和§13.3.1/3
中的过载解析
重载解析以七种不同的方式选择要调用的函数语言中的上下文…
,
- 首先,是候选函数的一个子集(具有适当数量的参数并满足某些其他条件的函数)(13.3.2)。
- 然后根据每个参数与的匹配所需的隐式转换序列(13.3.3.1)选择最佳可行函数
,
简而言之,编译器首先列出要使用的候选对象,然后尝试找到最合适和更有效的重载。
相关文章:
- 重载操作符+:表达式必须是整型或无作用域枚举类型
- 重载操作符
- 如何重载操作符==外模板类使用友元函数
- 重载*操作符,使其在左右两边都工作
- 重载操作符<对于非随机迭代器
- 在c++中重载操作符的时间和原因
- 如何在c++中重载=操作符来通过引用进行复制
- 如何在c++中获取定义为友元的重载操作符的地址
- 使用重载操作符的文件操作表达式没有给出预期的结果
- 重载操作符()
- 重载操作符()并在类内使用
- 类中的重载操作符+
- 定时使用重载操作符
- c++带类的重载操作符
- 用列表容器重载[]操作符
- 重载操作符=
- 任何重载操作符()的静态检测
- 重载操作符以处理类对象
- 在使用另一个类的类中重载操作符==
- 派生类和基类中的重载操作符不同