|
Boost : |
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2006-07-09 02:45:24
On 7/9/06, Kevin Spinar <spinarkm_at_[hidden]> wrote:
>
> The problem is, I don't see that it is feasible to write a
> clone-on-copy implementation that is compatible with assocative
> containers. To be usable with assocative containers, a clone_ptr must
> exhibit the following behavior:
This problem doesn't actually have to do with clone-on-write vs clone-on-copy,
the problem is that the less than operator is improperly defined for the
concept that is being modeled. As we established, the types being created
aren't really smart pointers but are actually smart objects. We are really
only accessing the objects indirectly via * and -> because we have no way of
more directly forwarding the interface in C++. Following this path, you
begin to realize that the internal address of the object is an
implementation detail and should be allowed to change without changing the
logical state the object. Just like with other types, copying an object
copies the state of the
object, only now the physical clone operation is performed lazily. If
defined, comparing objects before and after the physical clone operation
should not have different results, since the state is still logically the
same.
What this all means is that < should not compare the internal pointer value,
or rather, it shouldn't if you expect it to act correctly for the use that
we are describing (as a smart object). The same logic holds
true for other operations such as ==, !=, etc. Initially I was
imagining that the operations wouldn't be defined at all, and
if you wanted such functions you would have to do something like *left <
*right, and if you wished to use them in standard containers and algorithms
you would have to
specify the sorting predicate rather than using the default less (you simply
use an adapted predicate which performs the operation through a level
of indirection).
In retrospect, perhaps I was a bit premature about stating that the
operations should not be defined at all
in my response to
Thorsten, since it does make it more difficult to use with sorted
containers and
algorithms with default sorting predicates. Since we now consider * and ->
as a necessary evil and the closest one can get to overloading the .
operator, perhaps allowing some operations to be automatically forwarded
isn't a bad
thing. Taking that route, it would make sense to overload comparison
operations in such a way that just forwards the call
to the dynamically allocated object. This would allow you to work with the
objects intuitively with standard containers and algorithms without
explicitly having to specify sorting predicates and should go along with the
concept of the instantiation as being a smart object rather than a smart
pointer.
There is one more issue that I can see. Now that we are moving more towards
the concept of a smart object, how is a null pointer handled, or rather,
should it be allowable at all? Variants do not automatically allow a null
state, so should a smart object follow suit? If you take the approach that
the type cannot be in a null state, you may guarantee the user that they
always have a valid object, which could be very beneficial for all of the
same reasons that it is beneficial to have variants non-nullable. In
particular, this allows the user to safely avoid all null pointer checks
when they have a constructed smart object, which can potentially greatly
reduce errors.
The problem with this is, in addition to the fact that some users may
wish to have a nullable state, how
do you default-construct the object? For instance, in the case of an
abstract class, you wouldn't be able to default construct the type
unless perhaps a default child type were specified via a template argument
to the smart object type template itself (which would default to the first
type if left
unspecified). Ideally, I think it would be great to allow for
something like this, though it does increase the complexity of the
template. Since
only a few of us are showing serious interest, it's hard to say how common
or important such behavior could be. I wouldn't mind if such functionality
were excluded, but it is definately something to think about. If the desire
is there, perhaps both a "smart object" and a
"nullable smart object" concept could be maintained (with the former being
internally implemented with the latter), but really that can all be thought
about later, after everything else gets ironed out.
On 7/9/06, Kevin Spinar <spinarkm_at_[hidden]> wrote:
>
> Indeed. Perhaps poly_object?
>
Sounds good to me. It could possibly even be shortened to poly_obj if it
seems to long, though I don't know if "obj" is as immediately recognizable
as meaning "object" as "ptr" is to "pointer."
-- -Matt Calabrese
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk