msvc /permissive- std::string overloaded operator '=' is ambiguous

I suppose you meant it's fine in (2) but fails in (3)

Note that the #2 is initialization, which calls the constructor of std::string; the #3 is assignment, which calls the assignment operator of std::string. They're different things.

The invocation of assigment operator is ambiguous because the assignment operator of std::string has an overload taking char, which could be implicitly converted from long (which is a stardard conversion), then leads to ambiguity (with the assignment operators taking std::string, as the compiler complained). Both the implicit conversion sequence contain one user-defined conversion (from my to std::string or long), they have the same rank in onverload resolution.

The invocation of constructor is fine because it doesn't have such overload (taking char).


The problem is that in the case #2 there is used a constructor while in the case #3 there is used an assignment operator.

The assignment operator is overloaded like

basic_string& operator=(charT c);

But there is no constructor that accepts only one argument of the type charT

So for the case #2 there is used the user-defined conversion operator

operator std::string() { return myVal; };

and then the constructor

basic_string(basic_string&& str) noexcept;

In the case #3 there are two posiibilities.

The first one is to call the conversion operator

operator std::string() { return myVal; };

and then the assignment operator

basic_string& operator=(basic_string&& str)

And the second one is to call the conversion operator

operator long() { return std::stol(myVal); };

and then the assignment operator

basic_string& operator=(charT c);

It is interesting to note the following additional case.

If you will wrote

str.s = { my("ascas") };

then there will not be an ambiguity. The compiler will select the operator that accepts an std::initializer_list. That is it will select the assignment operator

basic_string& operator=(initializer_list<charT>);

In this case there will be used the conversion operator

operator long() { return std::stol(myVal); };

but as the string "ascas" can not be converted to the type long a runtime error will occur

terminate called after throwing an instance of 'std::invalid_argument'
  what():  stol