错误:为i386构建时,使用重载的运算符'[]'模棱两可 [英] Error: use of overloaded operator '[]' is ambiguous while building for i386
问题描述
考虑以下代码:
#include< stdio.h>#include< stdint.h>类test_class{上市:test_class(){}〜test_class(){}const int32_t运算符[](uint32_t索引)const{返回(int32_t)索引;}运算符const char *()const{返回"Hello World";}};int main(无效){test_class tmp;printf(%d \ n",tmp [3]);返回0;}
当我使用命令 clang ++ -arch i386 test.cc
生成这些代码时,在clang ++(Apple LLVM版本9.1.0(clang-902.0.39.1))上会产生以下内容:>
test.cc:24:21:错误:使用重载运算符'[]'不明确(操作数类型为'test_class'和'int')printf(%d \ n",tmp [3]);~~~ ^〜test.cc:10:17:注意:候选函数const int32_t运算符[](uint32_t索引)const^test.cc:24:21:注意:内置的候选运算符[](const char *,int)printf(%d \ n",tmp [3]);^test.cc:24:21:注意:内置的候选运算符[](const volatile char *,int)
但是,如果我只使用命令 clang ++ test.cc
i386上的重载运算符'[]'似乎与x86_64上的重载运算符不同,我想知道确切的区别是什么.
对 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)
.
这就是为什么您必须仔细考虑固定大小类型的原因:您可以获得意料之外的转换.
Consider the following code:
#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;
}
When I use command clang++ -arch i386 test.cc
to build those codes, it yields the following on clang++ (Apple LLVM version 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)
But there is no error if I just use command clang++ test.cc
It seems that overloading operator '[]' on i386 is different from on x86_64 and I want to know what the exactly distinction is.
There are two possible interpretations of tmp[3]
: the "obvious" one, calling test_class::operator[](int32_t)
, and the less obvious one, calling test_class::operator const char*()
to convert the object to a const char*
, and applying the index to that pointer.
To decide which of the overloads to use, the compiler looks at the conversions involved. There are two arguments for each overload: tmp
and 3
. For the first overload, tmp
needs no conversion, but 3
has to be converted from int
to int32_t
. For the second overload, tmp
needs to be converted to const char*
, and 3
does not have to be converted.
To choose the proper overload, the compiler has to look at the conversion set for each argument. For the first argument, tmp
, the first overload requires no conversion, and the second requires an integral conversion. So the first overload wins here. For the second argument, the first overload requires a user-defined conversion and the second requires no conversion. So the first conversion wins.
In short: the first overload wins on the first argument, and the second overload wins on the second argument. So the call is ambiguous.
You could add an overloaded operator[](int)
, which would resolve this particular complaint, but it would be an error with a compiler where int32_t
is a synonym for int
.
Your best bet is probably to get rid of operator[](int32_t)
and replace it with operator[](int)
.
This is why you have to think carefully about fixed-size types: you can get conversions that you aren't expecting.
这篇关于错误:为i386构建时,使用重载的运算符'[]'模棱两可的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!