C++ overloading conversion operator for custom type to std::string

Markus picture Markus · Aug 19, 2010 · Viewed 24k times · Source

I hope someone might be able to answer why the following doesn't work. Bear with me though, I am still very much a noob... I just cannot get to the bottom of why the following

using namespace std;
#include <string>
#include <iostream>

class testClass
{
public:
 operator char* () {return (char*)"hi";};
 operator int ()  {return 77;};
 operator std::string  () {return "hello";};
};

int main()
{
 char* c;
 int i;
 std::string s = "goodday";

 testClass t;

 c = t;
 i = t;
 s = t;

 cout<< "char: " << c << " int: " << i << " string: "<<s<<endl;

 return 0;
}

gives me a compile time error:

myMain.cpp: In function ‘int main()’:
myMain.cpp:23: error: ambiguous overload for ‘operator=’ in ‘s = t’
/usr/include/c++/4.2.1/bits/basic_string.h:500: note: candidates are: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:508: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:519: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]

If I do not attempt the assignment

s = t;

it does work.

I've been trying for hours to even comprehend the error message, but what's puzzling me most is that is does work for char*.

I'm grateful for any hint. Thanks! Markus

Answer

Tony Delroy picture Tony Delroy · Aug 19, 2010

What the error is trying to explain is that your assignment "s = t", where s is a std::string, would be valid if t were a std::string too, or if t were a [const] char*. Your conversion operators can convert a t into either, so the compiler has no basis on which to choose one over the other....

You can disambiguate this explicitly by selecting the conversion you want:

s = t.operator std::string();
s = static_cast<std::string>(t);

Or you can provide only one of the conversions and let the user do a further conversion when necessary.

You may find though - in the end - that any conversion operator is more trouble than it's worth... it's telling that std::string itself doesn't provide a conversion operator to const char*.