Jump to content
  • Advertisement
Sign in to follow this  
rozz666

MSVC operator problem

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by joanusdmentia
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).


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 this post


Link to post
Share on other sites
Quote:
Original post by rozz666
If 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 this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
Original post by rozz666
If 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 this post


Link to post
Share on other sites
Quote:
Original post by rozz666
Having 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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
Original post by rozz666
Having 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?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!