I have the following class:
#include <iostream>
#include <string>
using namespace std;
class CLS
{
int value;
string str_value;
public:
CLS(int param) { value = param; }
CLS(string param)
{
str_value = param;
}
};
int main()
{
CLS a(2);
CLS b = 3;
CLS c("4");
CLS d = "5"; // Error: invalid conversion from 'const char*' to 'int'
}
I searched for the reason why it is error with no luck.
Is it correct to construct with a string literal? if no, why? if yes, what is wrong with my code?
I am using gcc 5.3 with Code::Blocks 16.1.
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 ofother
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 ofother
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.
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)