Ошибка при компиляции для x86, но не для x64 - PullRequest
0 голосов
/ 29 октября 2018

Я написал следующий код:

struct Element
{
    int value;
};

struct Array
{
    operator Element*();
    operator const Element*() const;
    Element& operator[](const size_t nIndex);
    const Element& operator[](const size_t nIndex) const;
};

int main()
{
    Array values;
    if (values[0].value == 10)
    {

    }
    return 0;
}

Это отлично работает в x64. Но в x86 я получаю ошибку компилятора:

error C2666: 'Array::operator []': 4 overloads have similar conversions
note: could be 'const Element &Array::operator [](const std::size_t) const'
note: or       'Element &Array::operator [](const std::size_t)'
note: while trying to match the argument list '(Array, int)'
error C2228: left of '.value' must have class/struct/union

Если я закомментирую функцию неявного преобразования или добавлю префикс explicit, код будет скомпилирован в x86.

Но я не могу понять, почему этот код создает проблемы.

Почему компилятор не может решить сначала использовать неявное преобразование или метод доступа к массиву? Я думал, что operator[] выше по приоритету .

1 Ответ

0 голосов
/ 29 октября 2018

Тип 0, который является int, не соответствует типу аргументов вашего оператора [], поэтому необходимо преобразование.

Однако он соответствует встроенному оператору [] для типа указателя Element. В этом случае Clang выдает более описательное сообщение об ошибке: https://godbolt.org/z/FB3DzG (обратите внимание, что я изменил параметр на int64_t, чтобы это не удалось на x64).

Компилятор должен сделать одно преобразование, чтобы использовать оператор класса (индекс от int до size_t), и одно преобразование, чтобы использовать встроенный оператор (от Array до Element*), это неоднозначно, что один он должен использовать.

Он работает на x64, поскольку вашему оператору класса все еще требуется только одно преобразование для индекса, но встроенному оператору требуется 2, 1 для Array до Element* и один для индекса от int до int64_t это делает ваш оператор класса более подходящим и поэтому не является двусмысленным.

Решение состоит в том, чтобы либо сделать оператор преобразования явным (что в любом случае является хорошей идеей), либо гарантировать, что тип, который вы передаете в качестве индекса, соответствует типу, ожидаемому вашим оператором. В вашем примере вы можете просто передать 0U вместо 0.

...