  Search    Advertiser Disclosure
 TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK Specialized Dev Zones Research Center eBook Library .NET Java C++ Web Dev Architecture Database Security Open Source Enterprise Mobile Special Reports 10-Minute Solutions DevXtra Blogs Slideshow    Home » Tip Bank
Language: C++
Expertise: Intermediate
Sep 21, 2005

# Using a Function Call as an Lvalue

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++ doesallow 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 four 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 challengers)
``````
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 challengers)
{
static int scoreCard[playersCount];
return scoreCard[challengers];
}
``````
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 easy to see how to retrieve a score, but how does the assignment work? First, you make a refererence to Fred's score, then the assignment 18 is made to this reference. Not too difficult when you understand how the evaluation takes place and in what order.

If the function returned a pointer, 18 would be assigned to the pointer rather than to the memory address to which the pointer refers. Again, if you returned an int, 18 would never be assigned to the scoreCard array. That is why a function call is an Lvalue only if the result type is a reference. As you can see, references are not merely syntactic sugar or another way of expressing pointers, but were designed into the language by necessity to correctly hande cases such as this.

Here is the complete source code for the scores program:

``````
#include<iostream&Gt

using namespace std;

enum players
{
Fred,
Paul,
Jim,
Allen,
playersCount   // count of players
};

int& scores( players challengers)
{
static int scoreCard[playersCount];
return scoreCard[challengers];
}

int main()
{
scores(Fred)  = 5;
scores(Paul)  = 10;
scores(Jim)   = 15;
scores(Allen) = 20;

cout << scores(Fred)  << " " << endl;
cout << scores(Paul)  << " " << endl;
cout << scores(Jim)   << " " << endl;
cout << scores(Allen) << " " << endl;

return 0;
}
``````
Ron Stevenhaagen

 Submit a Tip Submit a Tip Browse "Java" Tips Browse "Java" Tips Browse All Tips Browse All Tips  