錯誤:操作符[]:2重載有類似的轉換。

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


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 个解决方案

#1


12  

If you read the rest of the error message (in the output window), it becomes a bit clearer:

如果您讀取了其余的錯誤消息(在輸出窗口中),則會變得更加清晰:

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>        ]

The compiler can't decide whether to use your overloaded operator[] or the built-in operator[] on the const T* that it can obtain by the following conversion function:

編譯器不能決定是否使用重載的運算符[]或在const T*上的內置運算符[],它可以通過以下轉換函數獲得:

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

Both of the following are potentially valid interpretations of the offending lines:

以下兩項是對違規行為的潛在有效解釋:

v.operator float*()[0]
v.operator[](0)

You can remove the ambiguity by explicitly casting the integer indices to be unsigned so that no conversion is needed:

您可以通過顯式地將整數索引轉換為無符號來消除歧義,以便不需要轉換:

_a[0] = v[static_cast<unsigned int>(0)];

or by changing your overloaded operator[]s to take an int instead of an unsigned int, or by removing the operator T*() const (and probably the non-const version too, for completeness).

或者通過更改重載的操作符[],將int改為int,或者刪除操作符T*() const(也可能是非const版本)。

#2


5  

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.

簡單地說:編譯器不知道是否要將v轉換為const float*,然后使用操作符[]作為指針,或者將0轉換為unsigned int,然后使用操作符(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].

Fix可能會刪除操作符[]。我想不出它給你的任何東西,轉換算子T*還沒有。如果您打算在操作符[]中添加一些bounds檢查,那么我將說用getPointer函數替換轉換操作符(因為一般來說,您不希望隱式地將安全的東西轉換為不安全的東西),或者執行std::vector做的,即用戶得到一個帶有&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.

另一個讓它編譯的更改是,更改操作符[],以獲取int參數,而不是unsigned int.然后在代碼中,編譯器明確地選擇不轉換的解釋。根據我的編譯器,即使使用無符號索引,仍然沒有歧義。這是不錯的。

#3


3  

When you the compiler compiles the following

當編譯器編譯下列內容時。

v[0]

it has to consider two possible interpretations

它必須考慮兩種可能的解釋。

v.operator T*()[0] // built-in []
v.operator[](0)    // overloaded [] 

Neither candidate is better than the other because each one requires a conversion. The first variant requires a user-defined conversion from v3<T> to T*. The second variant requires a standard conversion from int (0 is int) to unsigned int, since your overloaded [] requires an unsigned int argument. This makes these candidates uncomparable (neither is clearly better by C++ rules) and thus makes the call ambuguous.

兩個候選人都沒有比另一個更好,因為每個候選人都需要轉換。第一個變量需要由v3 到T*的用戶定義轉換。第二個變體要求從int(0)到unsigned int的標准轉換,因為您的重載[]需要一個無符號的int參數。這使得這些候選人無法與之相比(因為c++的規則,兩者都不是很好),從而使呼叫成為“伏擊”。

If you invoke the operator as

如果調用操作符。

v[0U]

the ambiguity will disappear (since 0U is already an unsigned int) and your overloaded [] will be selected. Alternatively, you can declare your overloaded [] with int argument. Or you can remove the conversion operator entirely. Or do something else to remove the ambiguity - you decide.

歧義將消失(因為0U已經是一個unsigned int),您的重載[]將被選中。或者,您可以使用int參數聲明您的重載[]。或者您可以完全刪除轉換操作符。或者做些別的事情來消除歧義——你決定。

#4


2  

It is your type conversion operator that is the culprit. v transformed to a float pointer. Now there are two operator []s possible, one is the built in subscript operator for float and the other being the one you defined on v, which one should the language pick, so it is an ambiguity according to ISO.

它是您的類型轉換操作符,是罪魁禍首。v轉換為浮點指針。現在有兩個操作符[],一個是在子腳本操作符中構建的,另一個是你在v中定義的那個,它應該是一個語言選擇,所以它是一個根據ISO的歧義。

#5


2  

Remember a class is a friend of itself:

記住,一個班級是自己的朋友:

v3(const v3<T> & v)
{
     _a[0] = v._a[0]; 
     _a[1] = v._a[1]; 
     _a[2] = v._a[2];
}

When copy something of the same type you are already exposed to the implementation details. Thus it is not a problem to access the implementation directly if that is appropriate. So from the constructor you can access the object you are copying directly and see its member '_a'.

當復制相同類型的內容時,您已經接觸到了實現細節。因此,如果合適的話,直接訪問實現並不是問題。因此,從構造函數中,您可以直接訪問正在復制的對象,並查看其成員“_a”。

If you want to know the original problem:

如果你想知道最初的問題:

The literal '1' in the context 'v[1]' is an integer (this is a synonym of signed integer). Thus to use the operator[] the compiler technically is required to insert a conversion from int to unisgned. The other alternative is to use the operator*() to get a pointer to the internal object and then use the [] operator on the pointer. Compiler is not allowed to make this choice and error out:

上下文“v[1]”中的文字“1”是一個整數(這是有符號整數的同義詞)。因此,要使用運算符[],需要從int向unisgned插入轉換。另一種方法是使用運算符*()來獲得指向內部對象的指針,然后在指針上使用[]操作符。編譯器不允許做出這個選擇和錯誤:

Compiler options:

編譯器選項:

 _a[1] = v[1];
 // Options 1:
 _a[1] = v.operator[]((unsigned int)1);
 // Options 2:
 _a[1] = v.operator*()[1];

To make it unabigious you can use an unsigned literal;

你可以使用無符號文字;

 _a[1] = v[1u];

In the long run it may be worth making this easier for the user.
Convert the operator[] to use int rather than unsigned int then you will get exact matches when integer literals (or you can have two sets of operator[]. One that uses int and one that uses unsigned int).

從長遠來看,讓用戶變得更容易是值得的。轉換操作符[]使用int而不是unsigned int,那么當整型文字(或者您可以有兩組操作符[])時,您將得到精確的匹配。一個使用int和一個使用unsigned int的方法。

#6


1  

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.

我沒有看到,直到James McNellis發布了完整的錯誤消息,但是這兩個v3::操作符()函數看起來是不明確的。

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

a)使用v3::運算符[](unsigned int) const,從而將int參數轉換為unsigned,或。

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

b)使用v3::操作符const T*() const轉換,然后是內置數組索引操作符。

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.

您可以通過使操作符[]參數int而不是未簽名的ints來避免這一點。但是更好的解決方案是避免隱式轉換為T*,而是提供一個顯式的數據()函數。

#7


0  

I had this same issue: I resolved it simply making the typecast operator explicit.

我遇到了同樣的問題:我解決了它,只是簡單地讓typecast操作符顯式。

#8


-2  

The const version doesn't modify anything. The non-const version allows you to assign things using array notation (v[3] = 0.5;).

const版本不修改任何東西。非const版本允許您使用數組表示法(v[3] = 0.5)來分配事物。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/11/13/72a2b8fbf69f0e958b4978904f27280d.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com