c++overloadingc++03disambiguation

Disambiguate cast operator when the target class has multiple constructors


I am trying to make utility for converting strings as I have a bad mix of interfaces needing strings in various containers (char*, std::string, custom string type) and formats (utf-8, utf-16, utf-32). So I had the idea to create a wrapper with cast operators to the various types. Like this:

#include <iostream>
#include <string>

struct X {
    operator std::string() { return std::string("string x"); }
    operator const char *() { return "zstring x"; }
};

X make_x() { return X(); }

int main()
{
    std::string y = make_x(); // this works
    std::string y(make_x()); // but this does not
    y = make_x(); // this does not work either
    y = std::string(make_x()); // nor does this, so it's about useless
    std::cout << y << std::endl;
    return 0;
}

But the problem is that if the type converts to both char * and std::string, the std::string constructor and assignment will be ambiguous between those two types. And I don't want to go through just char *, because the string may be originally given by range rather than as nul terminated, requiring extra copy to get a nul terminated one as well as making embedded nuls not work.

So is there any way to disambiguate these?

Important note: I am stuck with some C++03 compilers, so neither cast operator can be marked explicit.


Solution

  • I ended up creating one helper with cast operator to any character (char, wchar_t and either uint16_t or uint32_t depending on whether wchar_t is 32 or 16 bit) pointer type and another helper with cast operator to any basic_string (specialized to any of above, using custom traits for the non-standard types). That does not appear to be ambiguous anywhere.