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
- Message msg = "tester";
- std::string str = msg;
- cout << str << "\n"; // would print "tester"
- msg = 3.14159;
- float dec = msg + 2;
- cout << dec << "\n"; // would print "5.14159"
Expand|Select|Wrap|Line Numbers
- // part of class Message
- // either all of these have to be commented out...
- //operator char () const { return (char)this->val_integer; };
- //operator unsigned char () const { return (unsigned char)this->val_integer; };
- operator short int () const { return (short int)this->val_integer; };
- operator unsigned short int () const { return (unsigned short int)this->val_integer; };
- operator int () const { return (int)this->val_integer; }
- operator unsigned int () const { return (unsigned int)this->val_integer; }
- operator long int () const { return (long int)this->val_integer; };
- operator unsigned long int () const { return (unsigned long int)this->val_integer; };
- operator long long int () const { return (long long int)this->val_integer; };
- operator unsigned long long int () const { return (unsigned long long int)this->val_integer; };
- operator float () const { return (float)this->val_decimal; }
- operator double () const { return (double)this->val_decimal; }
- // ...or this has to be commented out, in order for any of it to work
- 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
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*
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
- #include <iostream>
- #include <string>
- class Message {
- public:
- operator const char * () const { return "Pi."; }
- operator double () const { return 3.14159; }
- };
- int main() {
- Message msg;
- std::string temp;
- temp = msg;
- std::cout << temp;
- return 0;
- }