operator[]重载调用歧义:Clang报错GCC编译通过,哪个编译器正确?
问题分析:Clang与GCC对重载
operator[]的行为差异 代码示例
#include <string> #include <string_view> struct object{ operator std::string(){return "";} }; struct foo{ foo operator[](std::string_view s){ return foo{}; } template <typename T> operator T(){ return object{}; } }; int main(){ foo f; std::string s = f["a"]; }
编译现象
- Clang 12.0.1编译报错:
error: use of overloaded operator '[]' is ambiguous (with operand types 'foo' and 'const char*')
note: candidate function foo operator[](std::string_view s)
note: built-in candidate operator[](long, const char*)
note: built-in candidate operator[](long, const volatile char*)
- GCC 7.5.0可成功编译。
原因解析
这段代码的歧义源于f["a"]的两种合法解析路径:
- 调用自定义
operator[]:const char*可通过std::string_view的构造函数隐式转换为std::string_view,匹配foo::operator[]。 - 调用内置数组下标运算符:
foo的模板转换运算符operator T()可被实例化为operator long()(或其他整数类型),将f转换为整数后,对const char*类型的"a"使用内置下标运算符。
根据C++标准,这两条路径的转换序列等级完全相同——都包含一次用户定义转换,因此编译器必须判定为重载歧义。
GCC 7.5.0能编译通过是因为其对转换序列的排序逻辑存在实现偏差,没有严格遵循标准;而Clang的报错行为才是符合C++标准的正确处理。
结论
Clang 12.0.1的行为是正确的,该代码确实存在重载歧义;GCC 7.5.0的编译通过属于实现层面的疏漏。
内容的提问来源于stack exchange,提问作者user9132451
相关产品推荐
相关产品推荐

