简体   繁体   中英

Error when compiling for x86 but not for x64

I have written the following code:

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;
}

This works fine in x64. But in x86 I get a compiler error:

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

If I comment out the implicit conversions func, or add the explicit prefix, the code is compilable in x86.

But I can't understand why this code makes trouble.

Why can't the compiler decide to use an implicit conversion first, or array accessor first? I thought operator[] is higher in precedence .

The type of 0 which is an int needs doesn't directly match the type of the arguments to your [] operator and therefore a conversion is needed.

However it does match the built in [] operator for the Element pointer type. Clang gives a more descriptive error message in this case: https://godbolt.org/z/FB3DzG (note I've changed the parameter to int64_t to make this fail on x64).

The compiler has to do one conversion to use your class operator (the index from int to size_t ) and one conversion to use the built in operator (from Array to Element* ) it is ambiguous which one it should use.

It works on x64 as your class operator still only requires a single conversion for the index but the built in operator needs 2, 1 from Array to Element* and one for the index from int to int64_t , this makes your class operator a better match and is therefore not ambiguous.

The solution is to either make the conversion operator explicit (which is a good idea anyway) or to ensure that the type you are passing as your index matches the type your operator is expecting. In your example case you can simply pass 0U instead of 0 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM