为 x86 而不是 x64 编译时出错

Error when compiling for x86 but not for x64

我写了下面的代码:

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

如果我注释掉隐式转换 func,或添加 explicit 前缀,则代码可在 x86 中编译。

但是我不明白这段代码为什么会出问题。

为什么编译器不能决定先使用隐式转换,还是先使用数组访问器?我以为 operator[]higher in precedence.

int 需要的 0 类型与 [] 运算符的参数类型不直接匹配,因此需要进行转换。

但是它确实匹配 Element 指针类型的内置 [] 运算符。在这种情况下,Clang 给出了更具描述性的错误消息:https://godbolt.org/z/FB3DzG(请注意,我已将参数更改为 int64_t 以使其在 x64 上失败)。

编译器必须进行一次转换才能使用您的 class 运算符(从 intsize_t 的索引)和一次转换才能使用内置运算符(从 ArrayElement*) 它应该使用哪一个是不明确的。

它适用于 x64,因为您的 class 运算符仍然只需要对索引进行一次转换,但内置运算符需要 2、1 从 ArrayElement* 和一个用于从 intint64_t 的索引,这使您的 class 运算符更匹配,因此不会产生歧义。

解决方案是使转换运算符显式(无论如何这是个好主意)或确保作为索引传递的类型与运算符期望的类型相匹配。在您的示例中,您可以简单地传递 0U 而不是 0.