An Lvalue is an expression that can appear on the left-hand side of an equals sign. Likewise, an Rvalue expression appears on the right-hand side of the equals sign. Therefore the assignment statement takes the following form:
Lvalue = Rvalue
The most common Lvalue expression is a variable name as follows:
int x = 7; // x is an Lvalue
Suppose you make x a constant. It is still considered to be an Lvalue. However, because you cannot change a constant value, it is referred to as a non-modifiable Lvalue:
const int x = 7; // ok initialze x with a const value
x = 8; // error attempting to assign to a non modifiable Lvalue
Is it possible to make an assignment to a function call for example:
foo(7) = 24;
At first glance, this makes no sense—a function isn't a variable, so how can you assign 24 to it? Actually, C++ does allow this, and it makes sense when you understand the mechanics behind how this expression is reduced. There is one rule in the C++ standard that states: "A function call is an Lvalue only if the result type is a reference." So, if the function prototype for foo is:
int& foo(int);
Then the expression above is legal C++.
Here's an example of how you might apply this. Suppose you want to keep track of 4 players' scores. First, you define an enumeration of the players' names to use as an index into an array of scores as follows:
enum players { Fred, Paul, Jim, Allen, playersCount // count of players };
Next, define the prototype for the function to which you wish to assign the scores:
int& scores(players player)
Notice that the result type of the function is a reference, so the function may be used as an Lvalue. Now, you just need to define the function as follows:
int& scores( players player)
{
static int scoreCard[playersCount];
return scoreCard[player];
}
The function has a static array that holds the scores and returns the score of the player you pass as an argument. You may assign and retrieve a score as follows:
int fredsScore;
scores(Fred) = 18;
fredsScore = scores(Fred);
It's obvious how a score is retrieved, but how does the assignment work? An assignment is being made to the return type in the function. If you look at the return statement a reference is made to Fred's score, then the assignment 18 is made to this reference.
Here is the complete source code for the scores program:
#include<iostream>
using namespace std;
enum players
{
Fred, Paul, Jim, Allen,
playersCount // count of players
};
int& scores( players player)
{
static int scoreCard[playersCount];
return scoreCard[player];
}
int main()
{
scores(Fred) = 5;
scores(Paul) = 10;
cout << scores(Fred) << endl;
cout << scores(Paul) << endl;
cout << (scores(Jim) = 15) << endl;
cout << (scores(Allen) = 20) << endl;
return 0;
}