c ++错误:operator []:2个重载具有类似的转换

Rak*_*age 3 c++ operator-overloading visual-c++

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;
}
Run Code Online (Sandbox Code Playgroud)

Jam*_*lis 12

如果您阅读了剩余的错误消息(在输出窗口中),它会变得更清晰:

1>        could be 'const float &v3<T>::operator [](unsigned int) const'
1>        with
1>        [
1>            T=float
1>        ]
1>        or       'built-in C++ operator[(const float *, int)'
1>        while trying to match the argument list '(const v3<T>, int)'
1>        with
1>        [
1>            T=float
1>        ]
Run Code Online (Sandbox Code Playgroud)

编译器不能决定是否使用过载operator[]或内置operator[]const T*,它可以通过如下转换功能获取:

operator const T * () const { return _a; }
Run Code Online (Sandbox Code Playgroud)

以下两个都是对违规行的潜在有效解释:

v.operator float*()[0]
v.operator[](0)
Run Code Online (Sandbox Code Playgroud)

您可以通过显式地将整数索引转换为无符号来消除歧义,以便不需要转换:

_a[0] = v[static_cast<unsigned int>(0)];
Run Code Online (Sandbox Code Playgroud)

或者通过更改你的重载operator[]s int代替a unsigned int,或者删除operator T*() const(也可能是非const版本,以获得完整性).

  • 解释`ptrdiff_t`的作用可能也很有用:错误信息只显示一半的真相,显示一个裸的`int` - 但是它是`ptrdiff_t`,碰巧是对'int`的typedef'编译器.在另一个系统中,`ptrdiff_t`可能是`long`,此时你将面对内置的'op []`和你自己的转换.在这种情况下,您将使用自己的一个,因为它更适合第一个参数(完成索引操作的对象 - "*this")和第二个参数相等. (4认同)

Ste*_*sop 5

简单来说:编译器不知道是否转换vconst float*然后使用operator[]for指针,或转换0unsigned int然后使用operator[]for const v3.

修复可能是删除operator[].我想不出它给你的任何东西,转换运算符到T*还没有.如果你打算进行一些边界检查operator[],那么我会说用getPointer函数替换转换操作符(因为通常你不想隐含地将安全的东西转换成不安全的东西),或者做什么呢std::vector,是用户得到一个指针&v[0].

允许它编译的另一个变化是operator[]改为采用int参数而不是unsigned int.然后在您的代码中,编译器明确地选择没有转换的解释.根据我的编译器,即使使用无符号索引,仍然没有歧义.这很好.