错误:使用重载运算符' []'在为i386构建时很模糊

时间:2018-04-02 08:05:34

标签: c++ operator-overloading x86-64 clang++ i386

请考虑以下代码:

#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不同,我想知道究竟是什么区别。

1 个答案:

答案 0 :(得分:2)

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)

这就是为什么你必须仔细考虑固定大小的类型:你可以获得你不期望的转换。