Please consider the following code:
#include <string.h>
class cstring {
public:
cstring(const char* str) : begin_(str), end_(str ? str + strlen(str) : 0)
{
}
size_t size() const
{
return (size_t)(end_ - begin_);
}
const char* data() const
{
return begin_;
}
private:
const char* begin_;
const char* end_;
};
class Name {
public:
Name(cstring str)
{
}
};
int main()
{
cstring str = "Hello World"; // OK
Name name = str; // OK
Name name2 = "James"; // error
}
Clang will output an error(GCC has similar output):
Source.cpp:37:10: error: no viable conversion from 'const char [6]' to 'Name'
Name name2 = "James"; // error
^ ~~~~~~~
Source.cpp:24:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from
'const char [6]' to 'const Name &' for 1st argument
class Name {
^
Source.cpp:26:5: note: candidate constructor not viable: no known conversion from 'const char [6]' to 'cstring' for 1st
argument
Name(cstring str)
^
1 error generated.
In the above code, due to the non-explicit constructors, const char*
can be implicitly converted to cstring
, and cstring
can be implicitly converted to Name
as well; hence the conversion sequence from const char*
to Name
exists. Then why Clang/GCC disallow such a copy-initialization (msvc allows this case)?
Gcc and clang are correct, only one user-defined conversion is allowed in implicit conversion sequence.
You could change copy-initialization to direct-initialization as
Name name2 ("James");
, in which only one user-defined conversion (fromconst char*
tocstring
) is required, and the convertedcstring
is passed as the argument to the constructor ofName
to constructname2
.