请考虑以下代码:
#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("%d\n", 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("%d\n", 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("%d\n", tmp[3]);
^
test.cc:24:21: note: built-in candidate operator[](const volatile char *, int)
但如果我只使用命令clang++ test.cc
似乎超载运营商&#39; []&#39;在i386上与x86_64不同,我想知道究竟是什么区别。
答案 0 :(得分:2)
对tmp[3]
有两种可能的解释:“明显的”解释test_class::operator[](int32_t)
,而不太明显的解释,调用test_class::operator const char*()
将对象转换为const char*
并将索引应用于该指针。
要确定要使用哪个重载,编译器会查看所涉及的转换。每个重载有两个参数:tmp
和3
。对于第一次重载,tmp
不需要转化,但3
必须从int
转换为int32_t
。对于第二次重载,tmp
需要转换为const char*
,并且3
不必转换。
要选择正确的重载,编译器必须查看每个参数的转换集。对于第一个参数tmp
,第一个重载不需要转换,第二个需要进行积分转换。所以第一次超载在这里获胜。对于第二个参数,第一个重载需要用户定义的转换,第二个重载不需要转换。所以第一次转换胜利。
简而言之:第一个参数的第一个重载获胜,第二个参数的第二个重载获胜。所以这个电话很模糊。
您可以添加一个重载的operator[](int)
,这会解决此特定投诉,但如果编译器int32_t
是int
的同义词,则会出错。
您最好的选择可能是摆脱operator[](int32_t)
并将其替换为operator[](int)
。
这就是为什么你必须仔细考虑固定大小的类型:你可以获得你不期望的转换。