[c++] Sorting a vector of custom objects

Sorting such a vector or any other applicable (mutable input iterator) range of custom objects of type X can be achieved using various methods, especially including the use of standard library algorithms like

Since most of the techniques, to obtain relative ordering of X elements, have already been posted, I'll start by some notes on "why" and "when" to use the various approaches.

The "best" approach will depend on different factors:

  1. Is sorting ranges of X objects a common or a rare task (will such ranges be sorted a mutiple different places in the program or by library users)?
  2. Is the required sorting "natural" (expected) or are there multiple ways the type could be compared to itself?
  3. Is performance an issue or should sorting ranges of X objects be foolproof?

If sorting ranges of X is a common task and the achieved sorting is to be expected (i.e. X just wraps a single fundamental value) then on would probably go for overloading operator< since it enables sorting without any fuzz (like correctly passing proper comparators) and repeatedly yields expected results.

If sorting is a common task or likely to be required in different contexts, but there are multiple criteria which can be used to sort X objects, I'd go for Functors (overloaded operator() functions of custom classes) or function pointers (i.e. one functor/function for lexical ordering and another one for natural ordering).

If sorting ranges of type X is uncommon or unlikely in other contexts I tend to use lambdas instead of cluttering any namespace with more functions or types.

This is especially true if the sorting is not "clear" or "natural" in some way. You can easily get the logic behind the ordering when looking at a lambda that is applied in-place whereas operator< is opague at first sight and you'd have to look the definition up to know what ordering logic will be applied.

Note however, that a single operator< definition is a single point of failure whereas multiple lambas are multiple points of failure and require a more caution.

If the definition of operator< isn't available where the sorting is done / the sort template is compiled, the compiler might be forced to make a function call when comparing objects, instead of inlining the ordering logic which might be a severe drawback (at least when link time optimization/code generation is not applied).

Ways to achieve comparability of class X in order to use standard library sorting algorithms

Let std::vector<X> vec_X; and std::vector<Y> vec_Y;

1. Overload T::operator<(T) or operator<(T, T) and use standard library templates that do not expect a comparison function.

Either overload member operator<:

struct X {
  int i{}; 
  bool operator<(X const &r) const { return i < r.i; } 
};
// ...
std::sort(vec_X.begin(), vec_X.end());

or free operator<:

struct Y {
  int j{}; 
};
bool operator<(Y const &l, Y const &r) { return l.j < r.j; }
// ...
std::sort(vec_Y.begin(), vec_Y.end());

2. Use a function pointer with a custom comparison function as sorting function parameter.

struct X {
  int i{};  
};
bool X_less(X const &l, X const &r) { return l.i < r.i; }
// ...
std::sort(vec_X.begin(), vec_X.end(), &X_less);

3. Create a bool operator()(T, T) overload for a custom type which can be passed as comparison functor.

struct X {
  int i{};  
  int j{};
};
struct less_X_i
{
    bool operator()(X const &l, X const &r) const { return l.i < r.i; }
};
struct less_X_j
{
    bool operator()(X const &l, X const &r) const { return l.j < r.j; }
};
// sort by i
std::sort(vec_X.begin(), vec_X.end(), less_X_i{});
// or sort by j
std::sort(vec_X.begin(), vec_X.end(), less_X_j{});

Those function object definitions can be written a little more generic using C++11 and templates:

struct less_i
{ 
    template<class T, class U>
    bool operator()(T&& l, U&& r) const { return std::forward<T>(l).i < std::forward<U>(r).i; }
};

which can be used to sort any type with member i supporting <.

4. Pass an anonymus closure (lambda) as comparison parameter to the sorting functions.

struct X {
  int i{}, j{};
};
std::sort(vec_X.begin(), vec_X.end(), [](X const &l, X const &r) { return l.i < r.i; });

Where C++14 enables a even more generic lambda expression:

std::sort(a.begin(), a.end(), [](auto && l, auto && r) { return l.i < r.i; });

which could be wrapped in a macro

#define COMPARATOR(code) [](auto && l, auto && r) -> bool { return code ; }

making ordinary comparator creation quite smooth:

// sort by i
std::sort(v.begin(), v.end(), COMPARATOR(l.i < r.i));
// sort by j
std::sort(v.begin(), v.end(), COMPARATOR(l.j < r.j));

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to stl

Why is it OK to return a 'vector' from a function? How to remove all the occurrences of a char in c++ string How to use the priority queue STL for objects? use std::fill to populate vector with increasing numbers What does iterator->second mean? How to set initial size of std::vector? Sorting a vector in descending order How do I reverse a C++ vector? Recommended way to insert elements into map Replace an element into a specific position of a vector

Examples related to sorting

Sort Array of object by object field in Angular 6 Sorting a list with stream.sorted() in Java How to sort dates from Oldest to Newest in Excel? how to sort pandas dataframe from one column Reverse a comparator in Java 8 Find the unique values in a column and then sort them pandas groupby sort within groups pandas groupby sort descending order Efficiently sorting a numpy array in descending order? Swift: Sort array of objects alphabetically