My class is like:
class X {
public:
:
:
:
operator const char*() const { return "foo"; };
operator std::string() const { return std::string( "foo" ); };
:
:
:
};
My hope was to be able to initialize a std::string implicitly, like this, but huge wall of errors:
string s1( x );
Even explicitly doesn't work:
string s1( (string) x );
However casting x to (const char*) works fine:
string s1( (const char*) x );
In addition to whatever solution you guys have, any other recommendations for making a type that should be as freely-convertible to and from C-style strings and std:string? (I already have constructors for X taking const char* and std::string as well as an x, and can take assignments from those types.
I am not sure my explanation will be 100% precise, but if not, hopefully, someone will clarify it. Instead of
std::stringandchar*, I will use a customYclass andintfor the sake of simplicity:With this code, in C++11/14, the compiler has two options how to proceed:
It converts
xtoY(0)byX::operator Y()and then passes thisY(0)to the move constructor ofY.It converts
xtoint(1)byX::operator int()and then passes thisint(1)to the converting constructorY::Y(int).Both options are equivalent and, therefore, generate ambiguity, which results in a compilation error.
In C++17, the situation is different due to guaranteed copy elision. Here, the call of move constructor in (1.) is elided, and, consequently, the first conversion sequence is selected, since it requires only 1 conversion instead of 2.
Anyway, this version:
also generates ambiguity in C++11/14, which, I must admit, I do not understand.