At first, "4"
is not std::string
, it's const char[2]
. Then
CLS c("4");
is direct initialization, the constructors of CLS
will be examined for initializing c
. CLS::CLS(string)
is picked up here, because const char[]
can be implicitly converted to std::string
via user-defined conversion (i.e. by std::string::string(const char*)
).
CLS d = "5";
is copy initialization,
(emphasis mine)
- If
T
is a class type, and the cv-unqualified version of the type of other
is not T
or derived from T
, or if T
is non-class type, but the type of other
is a class type, user-defined conversion sequences that can convert from the type of other
to T
(or to a type derived from T
if T
is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.
That means user-defined conversion sequences is required to convert const char[2]
to CLS
. Even const char[]
could be converted to std::string
, and std::string
could be converted to CLS
, but only one user-defined conversion is allowed in one implicit conversion sequence. That's why it's rejected.
(emphasis mine)
Implicit conversion sequence consists of the following, in this order:
1) zero or one standard conversion sequence;
2) zero or one user-defined conversion;
3) zero or one standard conversion sequence.
BTW: If you change it to using std::string
as the initializer expression explicitly it'll work fine. e.g.
CLS d = std::string{"5"}; // pass a temporary std::string constructed from "5" to the constructor of CLS
using namespace std::string_literals;
CLS d = "5"s; // "5"s is a string literal of type std::string (supported from C++14)