# MSVC operator problem

This topic is 4060 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I tried using MS VC++ 2005 express, but resigned due to this error:
class X {
private:

int xxx;

public:

operator int *() { return &xxx; }
int operator[](int i) { return xxx; }

void test()
{
X x;
unsigned idx = 5;

x[idx];  // C2666
}
};

error C2666: 'X::operator []' : 2 overloads have similar conversions d:\documents and settings\rp\moje dokumenty\visual studio 2005\projects\con_test\con_test\con_test.cpp(15): could be 'int X::operator [](int)' or 'built-in C++ operator[(int *, unsigned int)' while trying to match the argument list '(X, unsigned int)' It compiles under Borland Turbo C++, gcc, DevC++. Does anyone know if it's correct by means of ANSI C++?

##### Share on other sites
VS2005 is correct, and this is why providing both operator[] and a pointer cast operator is a bad idea (typical example being a string class). What's happening is your operator[] is expecting a signed int whereas you're passing in an unsigned. Normally this would be fine, the unsigned is cast to a signed (with a warning on higher warning levels) and operator[] is called. When you add the pointer cast operator though you now have 2 possible matches that both require only 1 cast, thus the error about ambiguity.

What version of GCC are you using? If it's recent I'm surprised it's letting that through.

##### Share on other sites
The VC++ ambiguity error seems to me to be the sane behaviour, though I don't know what the standard behaviour is. I'd say it depends on whether the standard considers a to be a binary expression operator (like +) or a member operator (like =).

As for the actual code, either the operator[] is redundant (it could be removed) or it has a different behaviour from casting to int* and subscripting into that buffer, at which point pain and misery due to implicit conversions are pretty much guaranteed in the near future.

##### Share on other sites
Maybe someone has a Comeau compiler to check it? :-)
I'd don't remember which version of gcc it is, but it came with openSUSE 10.2, so it's probably one of the newest.
As for the ambiguity, I understand why VC doesn't like it. The problem is, is it the way it should work. Theoretically, I could make:

class X {public:    int operator[](int idx} { // ... }    int& operator*() { // ... }    X operator+(int i) { // ... }};

and have ambiguity here too, since x[n] == *(x + n).
But that's not the point. If I have operator[] defined VC shouldn't use cast operator.

##### Share on other sites
Quote:
 Original post by joanusdmentiaVS2005 is correct, and this is why providing both operator[] and a pointer cast operator is a bad idea (typical example being a string class).

It's indeed for a string class. However it's not redundant, since I perform range checking in operator[] so I need separate operator const char * and operator[].

##### Share on other sites
Quote:
 Original post by rozz666If I have operator[] defined VC shouldn't use cast operator.

Exactly. But since you don't have operator[] defined, VC starts trying to make casts until it finds a matching definition. Since it finds two, it complains.

If you had the correct int * operator[](unsigned) defined, it would have been used. Expecting operator[](int) to be used in place of operator[](unsigned) is, to the compiler, the same as expecting operator[](int) to be used in place of operator[](const std::vector<enum {TRUE, FALSE, FILE_NOT_FOUND}> &): it will work at the cost of a type cast, whenever that cast is possible.

##### Share on other sites
Quote:
Original post by ToohrVyk
Quote:
 Original post by rozz666If I have operator[] defined VC shouldn't use cast operator.

Exactly. But since you don't have operator[] defined, VC starts trying to make casts until it finds a matching definition. Since it finds two, it complains.

If you had the correct int * operator[](unsigned) defined, it would have been used.

Having operator[](unsigned) defined is also ambiguous, isn't it?
There are still 2 possibilities.

##### Share on other sites
Quote:
 Original post by rozz666Having operator[](unsigned) defined is also ambiguous, isn't it?There are still 2 possibilities.

No. There is only one single possibility which may be used with exactly zero type casts, and that would be int X::operator[](unsigned). Any other possibilities require one or more type casts, and are thus excluded from the search. VC++ is perfectly happy with that, too.

The real question is whether type-casts should be attempted on the left-hand side of operator[] or not. Both Visual C++ and g++ agree on that point (because, if you remove the operator[] version, both will use the cast). Therefore, g++ has no excuse for not complaining (or barely mentioning) the ambiguity—the only two sane behaviours here are preventing type-casts to the left of operator[], or detecting ambiguity.

##### Share on other sites
Take a look at the STL's std::string,

1) Use it

2) Instead of overloading the pointer operator it has a function c_str(), not only does this make it more explicit what's happening, which I feel in this case is a good-thing, but it avoids the ambiguity.

##### Share on other sites
Quote:
Original post by ToohrVyk
Quote:
 Original post by rozz666Having operator[](unsigned) defined is also ambiguous, isn't it?There are still 2 possibilities.

No. There is only one single possibility which may be used with exactly zero type casts, and that would be int X::operator[](unsigned). Any other possibilities require one or more type casts, and are thus excluded from the search. VC++ is perfectly happy with that, too.

The real question is whether type-casts should be attempted on the left-hand side of operator[] or not. Both Visual C++ and g++ agree on that point (because, if you remove the operator[] version, both will use the cast). Therefore, g++ has no excuse for not complaining (or barely mentioning) the ambiguity—the only two sane behaviours here are preventing type-casts to the left of operator[], or detecting ambiguity.

Then I presume pointers have operator[] defined for all signed and unsigned integer types or at least int and unsigned?
But there's one thing I don't understand.
Suppose I have:

class X {public:    void f(unsigned);};class Y {public:    void f(int);    operator X();};void test(){    Y y;    y.f((unsigned) 5); // Y::f or X::f ?}

Do you see my point?
It's obvious that's Y::f. Why operator[] isn't working the same way?

1. 1
2. 2
3. 3
Rutin
18
4. 4
5. 5
JoeJ
13

• 14
• 10
• 23
• 9
• 56
• ### Forum Statistics

• Total Topics
632638
• Total Posts
3007601
• ### Who's Online (See full list)

There are no registered users currently online

×