Code:
#include <iostream>
#include <cstring>
class MyString
{
public:
MyString() {
std::cout << "1";
}
explicit MyString(const char *str) {
std::cout << "2";
}
};
int main()
{
MyString str1 = MyString("abcde");
MyString str2("abcde");
MyString str3 = "abcde";
return 0;
}
str1
and str2
are created just fine, printing out 2
. But when I run it with str3
I get the following error message:
Compilation failed due to following error(s).main.cpp: In function ‘int main()’:
main.cpp:19:19: error: conversion from ‘const char [6]’ to non-scalar type ‘MyString’ requested
19 | MyString str3 = "abcde";
Aren't all 3 lines supposed to call the second constructor, because of RVO? Or is it because I'm using a non-RVO compiler? I tried it both on CMake and gcc and both have the same error message.
I tried creating an operator=
and still got the same error, so it clearly isn't from RVO:
#include <iostream>
#include <cstring>
class MyString
{
public:
MyString() {
std::cout << "1";
}
explicit MyString(const char *str) {
std::cout << "2";
}
MyString& operator=(const char *str) {
std::cout << "3";
return *this;
}
};
int main()
{
MyString str1 = MyString("abcde");
MyString str2("abcde");
MyString str3 = "abcde";
return 0;
}
I searched around for quite a bit, but couldn't find an answer.
MyString str3 = "abcde";
performs copy initialization, which doesn't work with explicit constructors. More formally:
[...] if
T
is a class type, and the cv-unqualified version of the type of other is notT
or derived fromT
, or ifT
is non-class type, but the type ofother
is a class type, user-defined conversion sequences that can convert from the type of other toT
(or to a type derived fromT
ifT
is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.
Here T
is a class type (MyString
) and other
is not of a class type (const char[6]
), and there is no user-defined conversion sequence because one cannot contain explicit
constructors.