Ошибка: использование перегруженного оператора ‘[]’ неоднозначно при сборке для 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

Кажется, что оператор перегрузки ‘[]’ на i386 отличается от x86_64, и я хочу знать, в чем именно заключается различие.

3

Решение

Есть две возможные интерпретации 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),

Вот почему вы должны тщательно подумать о типах фиксированного размера: вы можете получить конверсии, которые вы не ожидаете.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]