Boost logo

Boost :

From: Michael Grundberg (michaelgrundberg_at_[hidden])
Date: 2003-10-24 01:16:13

"Peter Dimov" <pdimov_at_[hidden]> wrote:
> A very common use for associatives of shared_ptr is to track objects.
> You just create set< shared_ptr<void> > or map< shared_ptr<void>, Data

> > and use a shared_ptr<X> as a key to find the associated information;
> note that this works regardless of X.

I haven't used shared_ptrs in that way, but I can certainly see the

> In a typical scenario, both operator< implementations behave
> identically. The differences arise when an object has several
> addresses (usually with multiple inheritance, but not always) or, as
> in your case, several associated counts.
> Neither implementation is inherently more correct, but if the default
> operator< compared values, you'd have no way of getting the current
> behavior, while you can easily write a value-comparing predicate
> yourself.

Although one could also argue that the current operator < should be
converted into a predicate, leaving the operator < to compare against
addresses :)

> You should also consider shared_ptr's relationship with weak_ptr.
> weak_ptr's operator< can't compare values, since a weak_ptr can expire

> anytime, and then there would be no value to compare (accessing the
> value of a deleted pointer is undefined behavior in addition to being
> unsafe ;-)). You can't just use 0 as the value since operator< must be

> stable or the std::set's invariant will break as its elements start to

> expire.
> For this reason, weak_ptr's operator< compares count pointers, and
> there is an additional reason - consistency - for shared_ptr's
> operator< to match this behavior.

Ah, didn't think of this. I knew there was something I must have missed!

> I see three ways to deal with the problem, one hi-tech and two
> low-tech. :-)
> Hi-tech:
> Use something like the following function to create the shared_ptr
> instances associated with a resource:
> template<class R, R * pr> shared_ptr<R> make_resource_pointer() {
> static shared_ptr<R> q(pr, null_deleter());
> return q;
> }

This was really cool! I will try this out.

> Low-tech 1:
> Add
> static shared_ptr<R> pi(&i, null_deleter());
> after every
> int i;
> resource and use pi consistently. Or even hide 'int i' someplace safe
> and only expose pi to people.
> Low-tech 2:
> Comment out shared_ptr's operator<, compile, add the necessary
> predicate to every std::set pointed to by the compile errors. :-)
> > Also, the definition of the less operator for shared_ptr causes
> > std::set::find and std::find to operate in different ways, since the

> > later uses the == operator instead of <. Was this the intent?
> Yes, this is intentional, if not especially elegant. :-)

Ok :)

Thanks alot for your explanation, it helped clearing the smoke! If not
exactly the answers I wanted to hear, they at least make me able to
explain to fellow colleagues what they must and mustn't do when using
shared_ptrs :)


Boost list run by bdawes at, gregod at, cpdaniel at, john at