[Effective-cpp] Item 30: Proxy Classes

David.Nash at wallstreetsystems.com David.Nash at wallstreetsystems.com
Mon Jun 9 10:01:28 EDT 2003


At last, here it is.  Sorry about the delay:

More Effective C++
Item 30: Proxy Classes

This is another longish item as it deals with another fairly complicated 
issue: Proxy classes, objects of which stand-in for instances of other classes 
or built-in types.

Why might you need a stand-in for another object?  The first rationale Scott 
gives goes as follows:

You might want to write a "smart 2D array", kind of like a std::vector but in 
two dimensions.  you want to declare it like this:
	Array2D<int> data(10,20)

and use it like this:
	data[3][6]

Unfortunately there is no [][] operator you can define for user-define types, 
so you can't do this.  The answer is to define operator[] to return a proxy 
object, an Array1D, and to define operator[] for that class to access the 
other dimension.

The trick is that the user never sees the proxy objects, in a perfect world 
they wouldn't even know they exist.

However the world is far from perfect and there are a number of restrictions 
on what you can do with proxy objects.

First however, another example is given.  This time the proxy stands in for a 
char (or other type) returned from a string (it could be any container, 
really).

Why? The basic idea is that if we are reference counting, especially if we are 
using the much discussed and generally discredited Copy On Write, it is 
advantageous to know whether operator[] is being used to return an lvalue 
(which is being written to, and may need expensive copying to be performed) or 
an rvalue (which is not and consequently doesn’t).  Unfortunately you can't 
provide a different implementation because you can't overload on const-ness of 
return value.

So the answer is to delay the decision by returning a proxy that stands in for 
the char, and which has an assignment operator that causes the C.O.W. (or 
whatever) to be performed.  If the char is used as an rvalue, the assignment 
operator is never called - the cheap conversion to char operator is called 
instead.

Now, to return to the problems with proxies, they mostly stem from the fact 
that the proxy objects don’t behave exactly like the objects they are standing 
in for.  For instance, if you try to take the address of a char from a string 
that returns proxies, as described above, you would find that you are taking 
the address of the proxy not of the char it represents.  Also a proxy for a 
given class doesn’t have the same member functions as the class it stands for.

The result is that you need to give the proxy member functions for all the 
member functions in the object being held.






More information about the Effective-cpp mailing list