简体   繁体   中英

Modify std::less on a shared_ptr

This is what I have:

struct Foo {
  int index;
}
std::set<std::shared_ptr<Foo>> bar;

I want to order bar 's elements by their indices instead of by the default std::less<std::shared_ptr<T>> function, which relates the pointers.

I read I can type std::set<std::shared_ptr<Foo>, std::owner_less<std::shared_ptr<Foo>>> bar , but I'd prefer to stick to the previous syntax.

I tried defining std::less<std::shared_ptr<Foo>> , but it's not actually being used by the set functions. Is there a way I can achieve this?

If you want to compare by their indices, you'll have to write a comparator that checks by their indices. std::less<> will do the wrong thing (since it won't know about index ) and std::owner_less<> will do the wrong thing (since it still won't compare the Foo s, but rather has to do with ownership semantics of them).

You have to write:

struct SharedFooComparator {
    bool operator()(const std::shared_ptr<Foo>& lhs,
                    const std::shared_ptr<Foo>& rhs) const
    {
        return lhs->index < rhs->index;
    }
};

and use it:

std::set<std::shared_ptr<Foo>, SharedFooComparator> bar;

You could additionally generalize this to a generic comparator for shared_ptr's:

struct SharedComparator {
    template <typename T>
    bool operator()(const std::shared_ptr<T>& lhs,
                    const std::shared_ptr<T>& rhs) const
    {
        return (*lhs) < (*rhs);
    }
};

and then simply make Foo comparable.

You can provide your own specialization of less<shared_ptr<Foo>> in the std namespace.

namespace std
{
   template<>
   class less<shared_ptr<Foo>>
   {
   public:      
      bool operator()(const shared_ptr<Event>& a, const shared_ptr<Event>& b)
      {
         // Compare *a and *b in some way
      }
   };
}

Then you can form a set<shared_ptr<Foo>> without a comparator. I needed this for a priority_queue<shared_ptr<Foo>> , where I didn't want to use a priority_queue<Foo*, vector<Foo*>, int (*)(const Foo*, const Foo*)> . I am not proud of it, but it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM