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;
}
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
- What is the correct way to declare and use a FILE
When you the compiler compiles the following
it has to consider two possible interpretations
Neither candidate is better than the other because each one requires a conversion. The first variant requires a user-defined conversion from
v3<T>
toT*
. The second variant requires a standard conversion fromint
(0
isint
) tounsigned int
, since your overloaded[]
requires anunsigned int
argument. This makes these candidates uncomparable (neither is clearly better by C++ rules) and thus makes the call ambuguous.If you invoke the operator as
the ambiguity will disappear (since
0U
is already anunsigned int
) and your overloaded[]
will be selected. Alternatively, you can declare your overloaded[]
withint
argument. Or you can remove the conversion operator entirely. Or do something else to remove the ambiguity - you decide.The
const
version doesn't modify anything. The non-const
version allows you to assign things using array notation (v[3] = 0.5;
).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.
Remember a class is a friend of itself:
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'.
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:
Compiler options:
To make it unabigious you can use an unsigned literal;
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).
If you read the rest of the error message (in the output window), it becomes a bit clearer:
The compiler can't decide whether to use your overloaded
operator[]
or the built-inoperator[]
on theconst T*
that it can obtain by the following conversion function:Both of the following are potentially valid interpretations of the offending lines:
You can remove the ambiguity by explicitly casting the integer indices to be unsigned so that no conversion is needed:
or by changing your overloaded
operator[]
s to take anint
instead of anunsigned int
, or by removing theoperator T*() const
(and probably the non-const version too, for completeness).I had this same issue: I resolved it simply making the typecast operator explicit.