Boost logo

Boost :

From: Dietmar Kuehl (dietmar.kuehl_at_[hidden])
Date: 1999-12-08 13:50:57


Hi,
At 12:02 PM 12/8/99 -0500, jsiek_at_[hidden] wrote:
>So the main reason Dietmar does not like operator[] is that you need a
>proxy class to implement the various semantic flavors that are needed.

The proxy is one reason why I'm opposed to the 'operator[]()'. There
is another reason: 'operator[]()' needs to be a member function, it
cannot be a global function. Thus, it is impossible to add a version
taking a different kind of descriptor, eg. a wrapper around the original
descriptor, as argument. Why would somebody want to wrap a
descriptor? For example to cope with a temporarily modified graph
which somehow deals with the additional nodes (a simple example: a
network with added super source and super sink). The added function
could inspect the descriptor and depending on its value delegate the
request to the original property accessor or to some other accessor.

>And the requirements for this operator in iterators (containers too?)
>rules out proxies.

This is not my objection against proxies in this case, mainly because
there are no requirements for property accessors and property
accessors make lousy containers, at least in general.

The use of read/write accessors is quite common: Basically all flags
and temporary values use read/write accessors. However, even the
simplest of these uses, eg. Boolean flags, are rather likely to use
accessors which do not provide access to an lvalue. For example,
to avoid going through the whole graph to clear a flag in multiple
calls to an auxiliary algorithm (eg. a path search in the augmenting
flow algorithm) a simple technique using an integer can be used:

The Boolean flag accessor internally uses an integer accessor
and a current value: All values different from the current value are
considered to be the default value, eg. "false". Only for the objects
where the stored value is identical to the current value the accessor
returns "true". Clearing the flag for the whole graph amounts to just
incrementing a counter (except for the rare case of an overflow where
indeed the values for the whole graph have to be restored to some
intial value).

If there are two function, 'set()' and 'get()', to write and read the flag
this is easily implemented. Of course, you can also use a proxy in this
case, complicating things significantly. Actually, I think that the use
of proxied accessors would rather be common case than the exception!

Another thing which should be kept in mind is that a proxy "costs"
the implicit user defined conversion. Sometimes it is desirable to use
user defined conversions. It can be argued that the combination of
a read/write accessor with the need of a user defined conversion
would be rare. However, just one case is a loss of generality!

>Now one of the nice things about operator[] is that going the other
>way, using random_access_iterators for property accessors, will work
>for free (at least when the node descriptor is an integral type).
>Using arrays for property storage is one of the most common and also
>efficient methods, so I see a real benefit in making this easy.

It is fairly easy to put a simple property accessor into the library
which applies the suitable notation to random access iterators. It
is slightly more involved using such a property accessor but this
is only a minor problem.

Also note that all wrapping data accessors, ie. data accessors using
a different data accessor to actually store the data, need to be proxied
accessors if 'operator[]()' is to be used: It is not at all uncommon to
add a wrapper to perform additional actions like eg. an operation
count.

>And lastly, the operator[] results in code that is intuitive and easy
>to understand. We are all very use to the operator[] for mapping from
>one thing to another. Furthermore, operator[] is commonly used in the
>graph literature and textbooks.

I think it is minor gain in convenient notation vs. a rather powerful
tool and I'm pretty sure that I haven't thought of all possible
applications of the separation. Actually, I would rather change the
STL container and iterator requirements than accepting 'operator[]()'
for property accessors!

Regards,
  dk


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk