views:

753

answers:

4

In C++ is it possible to define conversion operators which are not class members? I know how to do that for regular operators (such as +), but not for conversion operators.

Here is my use case: I work with a C Library which hands me out a PA_Unichar *, where the library defines PA_Unichar to be a 16-bit int. It is actually a string coded in UTF-16. I want to convert it to a std::string coded in UTF-8. I have all the conversion code ready and working, and I am only missing the syntactic sugar that would allow me to write:

PA_Unichar *libOutput = theLibraryFunction();
std::string myString = libOutput;

(usually in one line without the temp variable).

Also worth noting:

  • I know that std::string doesn't define implicit conversion from char* and I know why. The same reason might apply here, but that's beside the point.

  • I do have a ustring, subclass of std::string that defines the right conversion operator from PA_Unichar*. It works but this means using ustring variables instead of std::string and that then requires conversion to std::string when I use those strings with other libraries. So that doesn't help very much.

  • Using an assignment operator doesn't work as those must be class members.

So is it possible to define implicit conversion operators between two types you don't control (in my case PA_Unichar* and std::string), which may or may not be class types?

If not what could be workarounds?

+6  A: 

What's wrong with a free function?

std::string convert(PA_Unichar *libOutput);

std::string myString = convert(theLibraryFunction());

Edit answering to the comment:

As DrPizza says: Everybody else is trying to plug the holes opened up by implicit conversions through replacing them with those explicit conversion which you call "visual clutter".

As to the temporary string: Just wait for the next compiler version. It's likely to come with rvalue references and its std::string implementation will implement move semantics on top of that, which eliminates the copy. I have yet to see a cheaper way to speedup your code than than by simply upgrading to a new compiler version.

sbi
what's wrong? Not much, but still, two things: - the visual clutter, when you have hundreds of meaningless calls to convert - this solutions implies the use of a temporary std::string. This means the data is copied twice, all the time. This may or may not be a problem, but is not very satisfying.
Jean-Denis Muys
Most compilers will optimize the extra copy out.
rlbond
jdmuys> rlbond is right, RVO is common and real in practice. You might wand to read that : http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
Klaim
+2  A: 

I don't think you can define "global" conversion operators. The standards say that conversion functions are special member functions. I would propse the following if I could consider the following syntax sugar:

struct mystring : public string
{
    mystring(PA_Unichar * utf16_string)
    {
     // All string functionality is present in your mystring.
     // All what you have to do is to write the conversion process.
     string::operator=("Hello World!");
     string::push_back('!');
     // any string operation...
    }
};

Be aware that polymorphic behavior of this class is broken. As long as you don't create an object of it through a pointer of type string* though, you are in the safe-side! So, this code is perfect:

mystring str(....);

As said before, the following code is broken!

string* str = new mystring(....);
....
delete str; // only deleting "string", but not "mystring" part of the object
// std::string doesn't define virtual destructor
AraK
+3  A: 

Implicit conversions are the devil, anyway. Make it explicit with a converting function call.

DrPizza
+1  A: 

No, you can't. What you could do as an alternative is to create a conversion constructor in the target class (not your case, as you want to convert to std::string - unless you derive it). But I agree to the other answers, I think an implicit conversion is not recommended in this case - especially because you're not converting from an object but from a pointer. Better to have a free function, your code will be easier to understand and the next programmer to inherit the code will for sure thank you.

Fabio Ceconello