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.
4. String Literal vs String Object. When we create a String object using the new() operator, it always creates a new object in heap memory. On the other hand, if we create an object using String literal syntax e.g. “Baeldung”, it may return an existing object from the String pool, if it already exists.
String literals or constants are enclosed in double quotes "" or with @"". A string contains characters that are similar to character literals: plain characters, escape sequences, and universal characters. Here are some examples of String Literals − Hello, World" "Welcome, \
A "string literal" is a sequence of characters from the source character set enclosed in double quotation marks (" "). String literals are used to represent a sequence of characters which, taken together, form a null-terminated string. You must always prefix wide-string literals with the letter L.
A string literal is a sequence of zero or more characters enclosed within single quotation marks. The following are examples of string literals: 'Hello, world!' 'He said, "Take it or leave it."'
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)
CLS a(2);
CLS b = 3;
CLS c("4");
CLS d = "5";
a
and c
are initialised with direct initialisation. b
and d
on the other hand use copy initialisation.
The difference is that for copy initialisation the compiler searches for a (single) user defined conversion from (in case of d
) char const *
(this is a bit inaccurate, see end of answer) to CLS
, whereas for direct initialisation all constructors are tried, where CLS(std::string)
can be used because there's a conversion std::string(char const *)
available.
Detail:
"5"
is a (C) string literal. It's type is char const [2]
. So first, a user defined conversion from that type to CLS
is searched. Because none is found, the standard conversion from Type[N]
to Type *
(with Type
= char const
and N
= 2
) is applied, resulting in a char const *
. Then the compiler tries to find a user defined conversion from that to CLS
. Because it doesn't find one, and there are no more standard conversions it could try available, compilation fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With