
Daryle Walker wrote:
1. I think that someone else has already been working on something like this. (It should be in our YahooGroups files area.)
Interesting, I'll have a look at that.
[...]
4. I know you have an issue with someone else on this list over your iterator/dereferencing policy, but I have an issue with it besides standard compliance. It's not consistent. The "->" gives the final object directly, but the "*" and "[]" only go one step and return a proxy. I don't like this mix.
Yes, I agree that it's a quite reasonable thing to dislike. Standards issues aside, it violates both reasonable expectations and what is generally considered good taste, so it is certainly not a good design unless it also delivers tangible benefits that can't be achieved in any other way. But I think it does. The "*" operator has to do a normal one-step dereferencing in order for the proxy_container to behave as a normal container of smart pointers. Since we are changing the primary iterators of the container, and not just creating an adapted iterator that is supposed to handle some situations but not other, we can't let the "*" operator do a double dereferencing. If we did, it would essentially cease to be an indirect container since we'd have no way of accessing the smart pointers. For example, when std::sort does assignments and swaps in the course of going about its business, it must do them on the pointers and not on the final objects, or the whole point of using an indirect container is lost. So that's why operator* and operator[] only do a single dereferencing. The "->" operator, on the other hand, doesn't really have very much practical use on a container of smart pointers if it only does single dereferencing. Even if the smart pointer does have some public members, like both shared_ptr and proxy do, those members would normally be of very little interest to the program that is iterating over the container. So since operator-> in this context is mostly unused anyway, why can't we redefine it to provide the final piece of the symmetry with direct containers? The way I see it, having different semantics for "*" and "->" ought to be in the same league as having different semantics for the assignment operator and the constructor for some class --- something that is legal according to the language definition and occasionally useful, but definitely something that should be viewed with a great deal of suspicion. The other aspects of the symmetry between direct and indirect containers still work without this controversial split level dereferencing, so it's actually not as central to the whole package as one might think, but I still think it would be a great pity to have drop it for purely formalistic reasons.
You claim that the directness is not needed for the latter two operators because proxy<T> takes assignments from T and converts to T. If so, then what is the point of using the proxy directly? Can I ever have an use for a "proxy<T>" object as itself?
Yes, absolutely, a proxy<T> is just as useful as a shared_ptr<T> (provided you don't need/want any pointer arithmetic), so it's definitely the intention that they should be useful outside the container as well. For example, a program that already is dealing with proxy<T> or shared_ptr<T> pointers can insert these pointers directly into a proxy_container. The effect then will be the same as when you insert a shared_ptr<T> into a Container< shared_ptr<T> >, that is: the T object won't be copied at all, and the pointer that is stored in the container will refer to the original T. Generally speaking, the intention behind the package is both that it should be easy to switch from direct to indirect containers, and that the resulting container should be a full-fledged container of smart pointers that can be used just like a Container< shared_ptr<T> > can.
[...]
(Your "proxy<T>" <-> T conversion policy could fail in some template contexts.)
Okay, that's something that needs to be investigated further then. /Christian