Boost logo

Boost Users :

Subject: Re: [Boost-users] shared_ptr to object in stl set container?
From: Rob Desbois (rob.desbois_at_[hidden])
Date: 2011-12-13 07:52:33


On 13 December 2011 10:07, Igor R <boost.lists_at_[hidden]> wrote:

> > -- I'm trying to use shared_ptr in a stl set, but am having trouble with
> find()
> > Any help? Documentation on this seems hard to find.
> >
> > -- Also, are the overloaded < and == useful or correct here?
>
>
> No, std algorithms won't call your comparison operators, because those
> of boost::shared_ptr do not compare pointees.
> You can define in your cpp something like this (operator ==() is not
> needed for your particular case):
>

operator<() is needed for set sorting, but he does need operator==() for
the find() to work.

namespace boost
> {
> template<class T>
> bool operator <(const shared_ptr<T> &lhs, const shared_ptr<T> &rhs)
> {
> if (!lhs && !rhs)
> return false;
> return *lhs < *rhs;
> }
> }
>
> Then move your operator <() out of Node class, and your programm will work.
>

Your program might work, but anyone else who might include your operator<()
definition in their own code will be extremely surprised when this doesn't
work as expected:
   ASSERT_FALSE(shared_ptr<Foo>(new Foo()) == shared_ptr<Foo>(new Foo()));

When I compare 2 pointers, smart or raw, I want to know if the pointers are
equal not the subobjects. This is the reason I would strongly recommend not
doing this, regardless of whether this code will be used by others or not.
Follow POLS - Principle Of Least Surprise; to override the equality
operator for all shared_ptr<> instances would be staggeringly surprising,
but even for 1 is unexpected.

A possible alternative, if you didn't wish to use boost::ptr_set for some
reason, would be to provide your own less than comparator for the set type,
though that still leaves you with the custom 'find' behaviour. For that you
could use std::find_if, but it won't give you as good performance as set's
own methods (linear vs. logarithmic IIRC).
I guess another alternative would be a shared_ptr wrapper that does the
dereferencing compare as you want, but that may prove tricky to do. I'd
still recommend ptr_container.

-- 
Rob Desbois
Blog: http://theotherbranch.wordpress.com/
"I disapprove of what you say, but I’ll defend to the death your right to
say it", Voltaire


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net