5.1.1/1 says that:
A literal is a primary expression. Its type depends on its form
(2.14). A string literal is an lvalue; all other literals are pvalues.
Does a string literal really a lvalue?
Yes.
If I code:
"foo" = "bar";
the compiler shuts at it.
"lvalue" does not imply assignable. Also, you're dealing with arrays.
You don't expect
int i[] = {1,2,3};
int j[] = {3,2,1};
i = j; // <-- this
to work, do you?
Or do i understand the string literal incorrectly.
I don't know. But you probably don't fully understand the lvalue
concept. Unfortunately, there is no short definnition for "lvalue" --
only a rule of thumb: "Can I take its address? If yes, it's an lvalue
(or an xvalue)".
Let me try to explain value categories in my own words:
The "value category" is a property of an *expression*. There are (now
in C++2011) three value categories:
- Lvalue
- Xvalue (eXpendable or eXpiring)
- PRvalue (pure rvalue)
In addition we use
- GLvalue (to refer to Lvalues and Xvalues)
- Rvalue (to refer to Xvalues and PRvalues)
GLvalues versus PRvalues:
-------------------------
GLvalues refer to objects that have an identity (region of storage)
PRvalues refer to plain values or temporary objects
This "axis" affects things like polymorphism, ability to take the
address of an object. GLvalues can have an abstract or incomplete
static type. PRvalues cannot. The dynamic type of a PRvalues is always
the same as its static type. For GLvalues the static and dynamic type
may be different.
Lvalues versus Rvalues:
-----------------------
Lvalues refer to things that probably continue to be of interest. They
always refer to an "object", to a region of storage. Modifying an
object referred to by an Lvalue expression is easily observable by the
rest of the program.
Rvalues refer to things that the rest of the program will not care
about anymore. Modifying an object referred to by an Rvalue is okay
because this object either has no identity or the user explicitly used
a cast to say "I don't care about this thing anymore". The ability to
detect Rvalues and temporary objects is what enables "move
semantics" (a C++2011 feature).
Examples:
string source();
int main() {
source(); // PRvalue
string x = "yay";
x; // Lvalue
move(x) // Xvalue (still refers to the same object but
// the expression has a different value category)
x+"123" // PRvalue (operator+ returns string by value)
x[1]; // Lvalue (operator[] returns a char&)
}
Cheers!
SG