I know there are topics that are similar to this one already (such as this).
The example given in this topic was this:
std::string & rs1 = std::strin
The problem is that a string literal is not of type std::string
or subclass thereof - it is of type char const[N]
.
Thus the type of the initializer is not reference compatible with the target type of the reference, and a temporary must be created and bound to the reference.
However, temporaries cannot be bound to non-const lvalue references. I.e. your case is equivalent to
std::string& s = std::string("Abcdefg");
which is, even according to you, clearly ill-formed.
Actually the precise reason it doesn't work is not because temporaries cannot be bound to non-const lvalue references, but rather that the initializer of a non-const lvalue reference is subject to certain requirements that char const[N]
cannot meet in this case, [dcl.init.ref]/5:
A reference to type “cv1
T1
” is initialized by an expression of type “cv2T2
” as follows:
If the reference is an lvalue reference and the initializer expression
- is an lvalue (but is not a bit-field), and “cv1
T1
” is reference-compatible with “cv2T2
” or- has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be implicitly converted to an lvalue of type “cv3 T3,” where “cv1
T1
” is reference-compatible with “cv3T3
”106(this conversion is selected by enumerating the applicable conversion functions (13.3.1.6) and choosing the best one through overload resolution (13.3)),then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).
Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.
- [..]
106) This requires a conversion function (12.3.2) returning a reference type.
The string literal may be an lvalue, but it's not a string
object. There's a temporary string
being created which is an rvalue.
First, a string is a const char *
or const char [N]
not a std::string
. So you're not directly assigning those char *
strings. std::string
has a constructor that takes a const char [N]
and the compiler automatically uses it to construct a new instance.
But when using const
for s2 you've just made it impossible for the compiler to assign the new std::string
instance to s2.
So in the end I think you've misunderstood the difference between a "string" of type const char [N]
and a "string" of type std::string
. The standard is referring to const char [N]
when it is talking about strings being an lvalue but you're attempting to apply that to a std::string
to which the standard's rule doesn't apply.