添加uint32_t转换运算符后,下标运算符重载出现编译歧义
问题分析:添加uint32_t转换运算符后operator[]编译歧义
问题背景
原本可正常编译的代码,在parent类中添加operator uint32_t() const转换运算符后,编译报错:
operator_overload.cpp: In member function ‘void top::run()’:
operator_overload.cpp:50:11: error: ambiguous overload for ‘operator[]’ (operand types are ‘parent’ and ‘const char [3]’)
p1["c0"].name = "name";
^
operator_overload.cpp:50:11: note: candidate: operator[](long int, const char*)
operator_overload.cpp:28:12: note: candidate: child& parent::operator[](const string&)
child& operator[](const std::string& n){
^~~~~~~~
报错原因
问题出在C++对operator[]的重载匹配规则,以及隐式转换的优先级:
- 没有转换运算符时,
p1["c0"]只会匹配parent类的operator[](const std::string&)——因为字符串字面量"c0"可以隐式转换为std::string,没有其他可选路径。 - 添加
operator uint32_t() const后,编译器多了一条可选路径:- 将
parent对象隐式转换为uint32_t(算术类型) - 触发内置的下标运算符:C++中
E1[E2]等价于*(E1 + E2),当E1是算术类型、E2是指针类型时,效果和E2[E1]一致。这里"c0"会转成const char*,编译器会把表达式解析为*( (uint32_t)p1 + "c0" ),对应内置的operator[](long int, const char*)。
- 将
这两条路径的隐式转换优先级相同,编译器无法判断该选哪一个,因此报出歧义错误。
解决办法
可以从以下几个方向解决:
- 给转换运算符加
explicit:禁止隐式转换parent到uint32_t,这样就不会触发内置运算符的匹配:explicit operator uint32_t() const{ return age; } - 修改成员
operator[]的参数类型:把const std::string&改成const char*,让字符串字面量直接匹配成员函数,无需隐式转std::string,优先级高于内置运算符:child& operator[](const char* n){ return *(child_by_name[n]); } - 调用时显式转换:在调用时明确把字符串字面量转成
std::string,消除歧义:p1[std::string("c0")].name = "name";
内容的提问来源于stack exchange,提问作者KPathak
相关产品推荐
相关产品推荐

