错误:在为 i386 构建时,使用重载运算符'[]'不明确

Error: use of overloaded operator '[]' is ambiguous while building for i386

本文关键字:运算符 不明确 重载 i386 在为 构建 错误      更新时间:2023-10-16

请考虑以下代码:

#include <stdio.h>
#include <stdint.h>
class test_class
{
public:
test_class() {}
~test_class() {}
const int32_t operator[](uint32_t index) const
{
return (int32_t)index;
}
operator const char *() const
{
return "Hello World";
}
};
int main(void)
{
test_class tmp;
printf("%dn", tmp[3]);
return 0;
}

当我使用命令clang++ -arch i386 test.cc来构建这些代码时,它会在clang++(Apple LLVM版本9.1.0(clang-902.0.39.1))上产生以下内容:

test.cc:24:21: error: use of overloaded operator '[]' is ambiguous (with operand types 'test_class' and 'int')
printf("%dn", tmp[3]);
~~~^~
test.cc:10:17: note: candidate function
const int32_t operator[](uint32_t index) const
^
test.cc:24:21: note: built-in candidate operator[](const char *, int)
printf("%dn", tmp[3]);
^
test.cc:24:21: note: built-in candidate operator[](const volatile char *, int)

但是如果我只使用命令clang++ test.cc,则没有错误

似乎 i386 上的重载运算符"[]"与 x86_64 上的不同,我想知道确切的区别是什么。

tmp[3]有两种可能的解释:"明显"的,调用test_class::operator[](int32_t),和不太明显的一种,调用test_class::operator const char*()将对象转换为const char*,并将索引应用于该指针。

为了确定使用哪个重载,编译器会查看所涉及的转换。每个重载有两个参数:tmp3。对于第一次重载,tmp不需要转换,但3必须从int转换为int32_t。对于第二次重载,tmp需要转换为const char*3不必转换。

若要选择适当的重载,编译器必须查看每个参数的转换集。对于第一个参数,tmp,第一个重载不需要转换,第二个重载需要积分转换。所以第一次重载在这里获胜。对于第二个参数,第一个重载需要用户定义的转换,第二个重载不需要转换。所以第一次转换获胜。

简而言之:第一个重载在第一个参数上获胜,第二个重载在第二个参数上获胜。所以这个电话是模棱两可的。

您可以添加一个重载的operator[](int),这将解决此特定问题,但这将是编译器的错误,其中int32_tint的同义词。

您最好的选择可能是摆脱operator[](int32_t)并将其替换为operator[](int).

这就是为什么您必须仔细考虑固定大小的类型:您可以获得意想不到的转化。