c++ error: operator []: 2 overloads have similar c

2019-07-04 09:42发布

template <typename T>
class v3 {
private:
    T _a[3];

public:
    T & operator [] (unsigned int i) { return _a[i]; }
    const T & operator [] (unsigned int i) const { return _a[i]; }

    operator T * () { return _a; }
    operator const T * () const { return _a; }

    v3() {
        _a[0] = 0; // works
        _a[1] = 0;
        _a[2] = 0;
    }

    v3(const v3<T> & v) {
        _a[0] = v[0]; // Error  1   error C2666: 'v3<T>::operator []' : 2 overloads have similar conversions
        _a[1] = v[1]; // Error  2   error C2666: 'v3<T>::operator []' : 2 overloads have similar conversions
        _a[2] = v[2]; // Error  3   error C2666: 'v3<T>::operator []' : 2 overloads have similar conversions
    }
};

int main(int argc, char ** argv)
{
    v3<float> v1;
    v3<float> v2(v1);

    return 0;
}

8条回答
冷血范
2楼-- · 2019-07-04 10:42

I didn't see it untill James McNellis posted the full error message, but the ambiguity is not between the two v3::operator[]() functions as it appears to be.

Instead, since there is no exact match between argument types, the compiler can't decide whether to:

a) Use v3::operator[](unsigned int) const, thereby converting the int argument to unsigned, or

b) Use the v3::operator const T*() const conversion followed by the built-in array indexing operator.

You can avoid this by making the operator[] arguments int's rather than unsigned ints. But a better solution would be to avoid an implicit conversion to T* and instead provide a Data() function that did that explicitly.

查看更多
唯我独甜
3楼-- · 2019-07-04 10:44

In simple terms: the compiler doesn't know whether to convert v to const float* and then use the operator[] for a pointer, or to convert 0 to unsigned int and then use the operator[] for const v3.

Fix is probably to remove the operator[]. I can't think of anything it gives you that the conversion operator to T* doesn't already. If you were planning to put some bounds-checking in operator[], then I'd say replace the conversion operators with getPointer functions (since in general you don't want to implicitly convert a safe thing to an unsafe thing), or do what std::vector does, which is that users get a pointer with &v[0].

Another change that lets it compile, is to change operator[] to take an int parameter instead of unsigned int. Then in your code, the compiler unambiguously chooses the interpretation with no conversion. According to my compiler, there is still no ambiguity even when using an unsigned index. Which is nice.

查看更多
登录 后发表回答