Sort std :: list <myclass *> with myclass :: operator <(myclass & other)

I have std::list<myclass*> and in my class I defined myclass::operator<(myclass &other) .

I use the std::list.sort() function, but it does not change anything in this list. Maybe this just sorts the pointers?

How can I sort the actual items in this list?

+6
source share
4 answers

You are sorting pointer values, not myclass values. You must write your own predicate to compare pointers by dereferencing:

 template <typename T> bool PComp(const T * const & a, const T * const & b) { return *a < *b; } std::vector<Foo*> myvec; std::list<Foo*> mylist; std::sort(myvec.begin(), myvec.end(), PComp<Foo>); mylist.sort(PComp<Foo>); 

By the way, I think you cannot sort std::list with std::sort from <algorithm> , because this is not random access. Use the sort member function instead, as MerickOWA says. (But this is usually less efficient than sorting a container with random access). Alternatively, you can immediately save your objects in a sorted container, for example std::set<Foo*, PPred> , where PPred is the functional version of the predicate:

 struct PPred { template <typename T> inline bool operator()(const T * a, const T * b) const { return *a < *b; } }; 
+12
source

Several answers suggest using a predicate that explicitly takes two pointers; this will work for your current case when you have a container with source pointers, but it will not work for any other type of dereferencing, for example, for smart pointers or iterators.

Why don't you go a more general route and go any type?

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

While a reference to a constant is optional for T* , for smart pointer types that are relatively expensive to copy (e.g. std::shared_ptr ) or cannot be copied (e.g. std::unique_ptr ), you must use

Alternatively, you can use something like Boost indirect_iterator , which moves indirectness to an iterator and can do for cleaner code.

+3
source

It sorts the pointer, since std :: sort (Container) uses the operator <defined by T. Here T is myclass *, then it is sorted using pointer comparison.

You can pass an arbitrary comparator functor to std :: sort to make one of them, take two myclass * and return the correct comparison:

 template<class T> struct ptr_comparison { bool operator()(T* a, T* b) { return *a < *b; } }; list<myclass*> mylist; // later mylist.sort(ptr_comparison<myclass>()); 
+2
source

Assuming you don't have NULL pointers in your list, just

 void ptrsorter( myclass *a, myclass *b ) { return *a < *b; } mylist.sort( ptrsorter ); 

or if you are lucky enough to use a more recent compiler (with C ++ 0x support), you can use a lambda expression:

 mylist.sort( []( myclass *a, myclass *b ) { return *a < *b } ); 
+2
source

Source: https://habr.com/ru/post/890873/


All Articles