470,871 Members | 1,658 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,871 developers. It's quick & easy.

Ambiguous overload problem

To start off, I'm using GCC4. Specifically, the MingW (setjmp/longjmp) build of GCC 4.2.1 on Windows XP x64.

I'm writing a class that abstracts a message, which can be either an integer (stored as long long int), a decimal (double), or a string (std::string). I basically want to overload most of a Message's operators so that the Message class feels more like a native type. For example...

Expand|Select|Wrap|Line Numbers
  1. Message msg = "tester";
  2. std::string str = msg;
  3. cout << str << "\n"; // would print "tester"
  5. msg = 3.14159;
  6. float dec = msg + 2;
  7. cout << dec << "\n"; // would print "5.14159"
...should ideally all work. It mostly does, except this code...

Expand|Select|Wrap|Line Numbers
  1. // part of class Message
  3. // either all of these have to be commented out...
  4. //operator char () const { return (char)this->val_integer; };
  5. //operator unsigned char () const { return (unsigned char)this->val_integer; };
  6. operator short int () const { return (short int)this->val_integer; };
  7. operator unsigned short int () const { return (unsigned short int)this->val_integer; };
  8. operator int () const { return (int)this->val_integer; }
  9. operator unsigned int () const { return (unsigned int)this->val_integer; }
  10. operator long int () const { return (long int)this->val_integer; };
  11. operator unsigned long int () const { return (unsigned long int)this->val_integer; };
  12. operator long long int () const { return (long long int)this->val_integer; };
  13. operator unsigned long long int () const { return (unsigned long long int)this->val_integer; };
  15. operator float () const { return (float)this->val_decimal; }
  16. operator double () const { return (double)this->val_decimal; }
  18. // ...or this has to be commented out, in order for any of it to work
  19. operator const char * () const { return (const char *)this->val_string.c_str(); }; // the 'const char *' matches exactly to one of std::basic_string's operator= handlers
Here, I'm controlling what happens when an instance of Message is used in an expression as a variable. That is, lines 2 and 6 in my usage example at the top are handled by this block of code.

Simply put, the problem is that I cannot handle strings if i'm also handling ints/floats at the same time, else it's telling me it's an ambiguous overload.

std::basic_string<T> defines the following three operator= overloads:
const std::basic_string<T, ..., ...> &
const T*

And I have tried to add a handler for each of them. Eg, "operator const std::basic_string<char> & ()" and "operator const char * ()" and "operator char ()". Alone, any of those works as I intend, but as soon as I also try to overload something else, it becomes ambiguous.

It makes sense that my char () handler and my const char * () handler will cause ambiguity, since std::basic_string is overloaded to handle both explicitly, but even if I comment my char handlers out it's still telling me that it's ambiguous. In fact, unless I comment everything but the const char * handler out, it tells me it's ambiguous. Even my double handler alone conflicts with std::basic_string's char handler. Should std::basic_string's operator=(char) overload be able to catch ints and floats like it is? Can I force the overload resolver to pick exact matches if they exists? I've looked over the GCC compile-time flags, and it doesn't appear that I can.

If I'm not making any sense, try taking this into a compiler to see what I mean:

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <string>
  4. class Message {
  5.     public:
  6.     operator const char * () const { return "Pi."; }
  7.     operator double () const { return 3.14159; }
  8. };
  10. int main() {
  11.     Message msg;
  12.     std::string temp;
  13.     temp = msg;
  14.     std::cout << temp;
  15.     return 0;
  16. }
In GCC, it's telling me that message can be converted into two types that basic_string will support: one for "const char *" (which is an exact match, and what I want), and one for "char" (apparently it thinks that my double overload is a good match for basic_string's char handler).
Mar 13 '08 #1
3 5427
1,275 Expert 1GB
i think you cant overload by differentiating the return types as for overloading the parameter types, number of parameters are taken into account.

Mar 13 '08 #2
I'm not overloading return types so much as defining what happens when I cast the instance of Message to another datatype.

Something to add to my original post- if I explicitly cast msg to const char *, it compiles. But for consistency and code length I would like to not have to do that.
Mar 13 '08 #3
9,208 Expert Mod 8TB
Your problem is the casting.

Generally, in C++ you cast a) to call relic C functions with arguments like void* or b) your C++ desing is screwed up.

You should a)remove every conversion operator function and then b) design a proper class hierarchy that implements your requirements,
Mar 13 '08 #4

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

1 post views Thread by Alan Johnson | last post: by
2 posts views Thread by Tim H | last post: by
9 posts views Thread by neildferguson | last post: by
11 posts views Thread by onkar | last post: by
9 posts views Thread by sebastian | last post: by
8 posts views Thread by Nikola | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.