Sorting a vector of custom objects












208















How does one go about sorting a vector containing custom (i.e. user defined) objects.

Probably, standard STL algorithm sort along with a predicate (a function or a function object) which would operate on one of the fields (as a key for sorting) in the custom object should be used.

Am I on the right track?










share|improve this question























  • Possible duplicate of Standard library sort and user defined types

    – MCCCS
    Jun 9 '18 at 13:18
















208















How does one go about sorting a vector containing custom (i.e. user defined) objects.

Probably, standard STL algorithm sort along with a predicate (a function or a function object) which would operate on one of the fields (as a key for sorting) in the custom object should be used.

Am I on the right track?










share|improve this question























  • Possible duplicate of Standard library sort and user defined types

    – MCCCS
    Jun 9 '18 at 13:18














208












208








208


83






How does one go about sorting a vector containing custom (i.e. user defined) objects.

Probably, standard STL algorithm sort along with a predicate (a function or a function object) which would operate on one of the fields (as a key for sorting) in the custom object should be used.

Am I on the right track?










share|improve this question














How does one go about sorting a vector containing custom (i.e. user defined) objects.

Probably, standard STL algorithm sort along with a predicate (a function or a function object) which would operate on one of the fields (as a key for sorting) in the custom object should be used.

Am I on the right track?







c++ stl sorting






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Sep 4 '09 at 17:05









AnkurAnkur

4,065165061




4,065165061













  • Possible duplicate of Standard library sort and user defined types

    – MCCCS
    Jun 9 '18 at 13:18



















  • Possible duplicate of Standard library sort and user defined types

    – MCCCS
    Jun 9 '18 at 13:18

















Possible duplicate of Standard library sort and user defined types

– MCCCS
Jun 9 '18 at 13:18





Possible duplicate of Standard library sort and user defined types

– MCCCS
Jun 9 '18 at 13:18












13 Answers
13






active

oldest

votes


















316














A simple example using std::sort



struct MyStruct
{
int key;
std::string stringValue;

MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
};

struct less_than_key
{
inline bool operator() (const MyStruct& struct1, const MyStruct& struct2)
{
return (struct1.key < struct2.key);
}
};

std::vector < MyStruct > vec;

vec.push_back(MyStruct(4, "test"));
vec.push_back(MyStruct(3, "a"));
vec.push_back(MyStruct(2, "is"));
vec.push_back(MyStruct(1, "this"));

std::sort(vec.begin(), vec.end(), less_than_key());




Edit: As Kirill V. Lyadvinsky pointed out, instead of supplying a sort predicate, you can implement the operator< for MyStruct:



struct MyStruct
{
int key;
std::string stringValue;

MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

bool operator < (const MyStruct& str) const
{
return (key < str.key);
}
};


Using this method means you can simply sort the vector as follows:



std::sort(vec.begin(), vec.end());


Edit2: As Kappa suggests you can also sort the vector in the descending order by overloading a > operator and changing call of sort a bit:



struct MyStruct
{
int key;
std::string stringValue;

MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

bool operator > (const MyStruct& str) const
{
return (key > str.key);
}
};


And you should call sort as:



std::sort(vec.begin(), vec.end(),greater<MyStruct>());





share|improve this answer





















  • 2





    Could you explain why you made the compare function in the struct less_than_key (in the first) example inline?

    – kluka
    May 15 '13 at 18:10






  • 1





    and another question/note: if one would like to have multiple sorting methods (for different attributes) in a class the way of overloading the < operator is probably not an option, right?

    – kluka
    May 15 '13 at 18:28






  • 5





    A cool thing is to provide also operator> method. This will allow us to sort in reverse order like: std::sort(vec.begin(), vec.end(), greater<MyStruct>()), which is clean and elegant.

    – kappa
    May 30 '14 at 23:21






  • 3





    @Bovaz You need to #include <functional> to use "std::greater".

    – Nick Hartung
    Aug 31 '15 at 15:21








  • 2





    @kappa: Where you could just have operator< and use either std::sort(vec.begin(), vec.end()); or std::sort(vec.rbegin(), vec.rend()); depending on whether you want to have ascending or descending order.

    – Pixelchemist
    May 19 '16 at 22:24





















126














In the interest of coverage. I put forward an implementation using lambda expressions.



C++11



#include <vector>
#include <algorithm>

using namespace std;

vector< MyStruct > values;

sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
{
return lhs.key < rhs.key;
});


C++14



#include <vector>
#include <algorithm>

using namespace std;

vector< MyStruct > values;

sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
{
return lhs.key < rhs.key;
});





share|improve this answer





















  • 13





    extra +1 for including the #includes

    – Anne
    May 3 '16 at 17:35






  • 2





    To be clear, this results in ascending order; use > instead of < to get descending order.

    – bhaller
    Apr 27 '17 at 4:53



















52














You could use functor as third argument of std::sort, or you could define operator< in your class.



struct X {
int x;
bool operator<( const X& val ) const {
return x < val.x;
}
};

struct Xgreater
{
bool operator()( const X& lx, const X& rx ) const {
return lx.x < rx.x;
}
};

int main () {
std::vector<X> my_vec;

// use X::operator< by default
std::sort( my_vec.begin(), my_vec.end() );

// use functor
std::sort( my_vec.begin(), my_vec.end(), Xgreater() );
}





share|improve this answer





















  • 4





    why do we need to add const at the end of function signature?

    – prongs
    Jun 14 '13 at 11:40






  • 4





    The function doesn't change the object so it is const.

    – Kirill V. Lyadvinsky
    Jul 2 '13 at 8:35











  • If that is the case then why we pass "const X& val", I assume that passing the value as const to a function makes the function think that its value is not going to be changed.

    – Prashant Bhanarkar
    Aug 22 '16 at 6:47











  • @PrashantBhanarkar The const keyword at the end of the signature specifies that the operator() function does not change the instance of the Xgreater struct (which in general could have member variables), whereas indicating const for the input values only specifies that those input values are immutable.

    – schester
    Dec 28 '17 at 19:35





















13














You are on the right track. std::sort will use operator< as comparison function by default. So in order to sort your objects, you will either have to overload bool operator<( const T&, const T& ) or provide a functor that does the comparison, much like this:



 struct C {
int i;
static bool before( const C& c1, const C& c2 ) { return c1.i < c2.i; }
};

bool operator<( const C& c1, const C& c2 ) { return c1.i > c2.i; }

std::vector<C> values;

std::sort( values.begin(), values.end() ); // uses operator<
std::sort( values.begin(), values.end(), C::before );


The advantage of the usage of a functor is that you can use a function with access to the class' private members.






share|improve this answer


























  • Missed that one: provide a member function operator<.

    – xtofl
    Sep 4 '09 at 17:13






  • 1





    It is better to make operator< a member of class (or struct), because global one could use protected or private members. Or you should make it a friend of struct C.

    – Kirill V. Lyadvinsky
    Sep 4 '09 at 17:25



















11














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





  • sort,


  • stable_sort,


  • partial_sort or


  • partial_sort_copy.


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));





share|improve this answer


























  • In 2. case you wrote bool X_less(X const &l, X const &r) const { return l.i < r.i; } for comparator but the const keywords should be removed (as it's not a member function).

    – PolGraphic
    Aug 29 '16 at 17:43











  • @PolGraphic: Correct - in case 1 as well.

    – Pixelchemist
    Aug 29 '16 at 21:45











  • @Pixelchemist how would I use the (4.) lambda approach when not using std::sort or similar, but needed an instance of Compare, e.g. when instantiating a std::set ?

    – azrdev
    Mar 28 '18 at 13:56






  • 1





    @azrdev: A function template that capture the type of the closure to pass it as a template parameter to set: template<class T, class C> std::set<T, C> make_set(C const& compare) { return std::set<T, C>{ compare }; } which could be used like auto xset = make_set<X>((auto && l, auto && r) { return l.i < r.i; });.

    – Pixelchemist
    Mar 29 '18 at 19:19



















4














Yes, std::sort() with third parameter (function or object) would be easier. An example:
http://www.cplusplus.com/reference/algorithm/sort/






share|improve this answer


























  • Not exactly a link only answer but at least a single line example would be useful.

    – Manos Nikolaidis
    Dec 31 '15 at 11:20



















3














In your class, you may overload the "<" operator.



class MyClass
{
bool operator <(const MyClass& rhs)
{
return this->key < rhs.key;
}
}





share|improve this answer

































    2














    Below is the code using lambdas



    #include "stdafx.h"
    #include <vector>
    #include <algorithm>

    using namespace std;

    struct MyStruct
    {
    int key;
    std::string stringValue;

    MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
    };

    int main()
    {
    std::vector < MyStruct > vec;

    vec.push_back(MyStruct(4, "test"));
    vec.push_back(MyStruct(3, "a"));
    vec.push_back(MyStruct(2, "is"));
    vec.push_back(MyStruct(1, "this"));

    std::sort(vec.begin(), vec.end(),
    (const MyStruct& struct1, const MyStruct& struct2)
    {
    return (struct1.key < struct2.key);
    }
    );
    return 0;
    }





    share|improve this answer































      2














      I was curious if there is any measurable impact on performance between the various ways one can call std::sort, so I've created this simple test:



      $ cat sort.cpp
      #include<algorithm>
      #include<iostream>
      #include<vector>
      #include<chrono>

      #define COMPILER_BARRIER() asm volatile("" ::: "memory");

      typedef unsigned long int ulint;

      using namespace std;

      struct S {
      int x;
      int y;
      };

      #define BODY { return s1.x*s2.y < s2.x*s1.y; }

      bool operator<( const S& s1, const S& s2 ) BODY
      bool Sgreater_func( const S& s1, const S& s2 ) BODY

      struct Sgreater {
      bool operator()( const S& s1, const S& s2 ) const BODY
      };

      void sort_by_operator(vector<S> & v){
      sort(v.begin(), v.end());
      }

      void sort_by_lambda(vector<S> & v){
      sort(v.begin(), v.end(), ( const S& s1, const S& s2 ) BODY );
      }

      void sort_by_functor(vector<S> &v){
      sort(v.begin(), v.end(), Sgreater());
      }

      void sort_by_function(vector<S> &v){
      sort(v.begin(), v.end(), &Sgreater_func);
      }

      const int N = 10000000;
      vector<S> random_vector;

      ulint run(void foo(vector<S> &v)){
      vector<S> tmp(random_vector);
      foo(tmp);
      ulint checksum = 0;
      for(int i=0;i<tmp.size();++i){
      checksum += i *tmp[i].x ^ tmp[i].y;
      }
      return checksum;
      }

      void measure(void foo(vector<S> & v)){

      ulint check_sum = 0;

      // warm up
      const int WARMUP_ROUNDS = 3;
      const int TEST_ROUNDS = 10;

      for(int t=WARMUP_ROUNDS;t--;){
      COMPILER_BARRIER();
      check_sum += run(foo);
      COMPILER_BARRIER();
      }

      for(int t=TEST_ROUNDS;t--;){
      COMPILER_BARRIER();
      auto start = std::chrono::high_resolution_clock::now();
      COMPILER_BARRIER();
      check_sum += run(foo);
      COMPILER_BARRIER();
      auto end = std::chrono::high_resolution_clock::now();
      COMPILER_BARRIER();
      auto duration_ns = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();

      cout << "Took " << duration_ns << "s to complete round" << endl;
      }

      cout << "Checksum: " << check_sum << endl;
      }

      #define M(x)
      cout << "Measure " #x " on " << N << " items:" << endl;
      measure(x);

      int main(){
      random_vector.reserve(N);

      for(int i=0;i<N;++i){
      random_vector.push_back(S{rand(), rand()});
      }

      M(sort_by_operator);
      M(sort_by_lambda);
      M(sort_by_functor);
      M(sort_by_function);
      return 0;
      }


      What it does is it creates a random vector, and then measures how much time is required to copy it and sort the copy of it (and compute some checksum to avoid too vigorous dead code elimination).



      I was compiling with g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)



      $ g++ -O2 -o sort sort.cpp && ./sort


      Here are results:



      Measure sort_by_operator on 10000000 items:
      Took 0.994285s to complete round
      Took 0.990162s to complete round
      Took 0.992103s to complete round
      Took 0.989638s to complete round
      Took 0.98105s to complete round
      Took 0.991913s to complete round
      Took 0.992176s to complete round
      Took 0.981706s to complete round
      Took 0.99021s to complete round
      Took 0.988841s to complete round
      Checksum: 18446656212269526361
      Measure sort_by_lambda on 10000000 items:
      Took 0.974274s to complete round
      Took 0.97298s to complete round
      Took 0.964506s to complete round
      Took 0.96899s to complete round
      Took 0.965773s to complete round
      Took 0.96457s to complete round
      Took 0.974286s to complete round
      Took 0.975524s to complete round
      Took 0.966238s to complete round
      Took 0.964676s to complete round
      Checksum: 18446656212269526361
      Measure sort_by_functor on 10000000 items:
      Took 0.964359s to complete round
      Took 0.979619s to complete round
      Took 0.974027s to complete round
      Took 0.964671s to complete round
      Took 0.964764s to complete round
      Took 0.966491s to complete round
      Took 0.964706s to complete round
      Took 0.965115s to complete round
      Took 0.964352s to complete round
      Took 0.968954s to complete round
      Checksum: 18446656212269526361
      Measure sort_by_function on 10000000 items:
      Took 1.29942s to complete round
      Took 1.3029s to complete round
      Took 1.29931s to complete round
      Took 1.29946s to complete round
      Took 1.29837s to complete round
      Took 1.30132s to complete round
      Took 1.3023s to complete round
      Took 1.30997s to complete round
      Took 1.30819s to complete round
      Took 1.3003s to complete round
      Checksum: 18446656212269526361


      Looks like all the options except for passing function pointer are very similar, and passing a function pointer causes +30% penalty.



      It also looks like the operator< version is ~1% slower (I repeated the test multiple times and the effect persists), which is a bit strange as it suggests that the generated code is different (I lack skill to analyze --save-temps output).






      share|improve this answer

































        1














            // sort algorithm example
        #include <iostream> // std::cout
        #include <algorithm> // std::sort
        #include <vector> // std::vector
        using namespace std;
        int main () {
        char myints = {'F','C','E','G','A','H','B','D'};
        vector<char> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
        // using default comparison (operator <):
        sort (myvector.begin(), myvector.end()); //(12 32 45 71)26 80 53 33
        // print out content:
        cout << "myvector contains:";
        for (int i=0; i!=8; i++)
        cout << ' ' <<myvector[i];
        cout << 'n';
        system("PAUSE");
        return 0;
        }





        share|improve this answer































          1














          You can use user defined comparator class.



          class comparator
          {
          int x;
          bool operator()( const comparator &m, const comparator &n )
          {
          return m.x<n.x;
          }
          }





          share|improve this answer































            0














            To sort a vector you can use the sort() algorithm in .



            sort(vec.begin(),vec.end(),less<int>());


            The third parameter used can be greater or less or any function or object can also be used. However the default operator is < if you leave third parameter empty.



            // using function as comp
            std::sort (myvector.begin()+4, myvector.end(), myfunction);
            bool myfunction (int i,int j) { return (i<j); }

            // using object as comp
            std::sort (myvector.begin(), myvector.end(), myobject);





            share|improve this answer































              0














              typedef struct Freqamp{
              double freq;
              double amp;
              }FREQAMP;

              bool struct_cmp_by_freq(FREQAMP a, FREQAMP b)
              {
              return a.freq < b.freq;
              }

              main()
              {
              vector <FREQAMP> temp;
              FREQAMP freqAMP;

              freqAMP.freq = 330;
              freqAMP.amp = 117.56;
              temp.push_back(freqAMP);

              freqAMP.freq = 450;
              freqAMP.amp = 99.56;
              temp.push_back(freqAMP);

              freqAMP.freq = 110;
              freqAMP.amp = 106.56;
              temp.push_back(freqAMP);

              sort(temp.begin(),temp.end(), struct_cmp_by_freq);
              }


              if compare is false, it will do "swap".






              share|improve this answer























                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1380463%2fsorting-a-vector-of-custom-objects%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                13 Answers
                13






                active

                oldest

                votes








                13 Answers
                13






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                316














                A simple example using std::sort



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                };

                struct less_than_key
                {
                inline bool operator() (const MyStruct& struct1, const MyStruct& struct2)
                {
                return (struct1.key < struct2.key);
                }
                };

                std::vector < MyStruct > vec;

                vec.push_back(MyStruct(4, "test"));
                vec.push_back(MyStruct(3, "a"));
                vec.push_back(MyStruct(2, "is"));
                vec.push_back(MyStruct(1, "this"));

                std::sort(vec.begin(), vec.end(), less_than_key());




                Edit: As Kirill V. Lyadvinsky pointed out, instead of supplying a sort predicate, you can implement the operator< for MyStruct:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator < (const MyStruct& str) const
                {
                return (key < str.key);
                }
                };


                Using this method means you can simply sort the vector as follows:



                std::sort(vec.begin(), vec.end());


                Edit2: As Kappa suggests you can also sort the vector in the descending order by overloading a > operator and changing call of sort a bit:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator > (const MyStruct& str) const
                {
                return (key > str.key);
                }
                };


                And you should call sort as:



                std::sort(vec.begin(), vec.end(),greater<MyStruct>());





                share|improve this answer





















                • 2





                  Could you explain why you made the compare function in the struct less_than_key (in the first) example inline?

                  – kluka
                  May 15 '13 at 18:10






                • 1





                  and another question/note: if one would like to have multiple sorting methods (for different attributes) in a class the way of overloading the < operator is probably not an option, right?

                  – kluka
                  May 15 '13 at 18:28






                • 5





                  A cool thing is to provide also operator> method. This will allow us to sort in reverse order like: std::sort(vec.begin(), vec.end(), greater<MyStruct>()), which is clean and elegant.

                  – kappa
                  May 30 '14 at 23:21






                • 3





                  @Bovaz You need to #include <functional> to use "std::greater".

                  – Nick Hartung
                  Aug 31 '15 at 15:21








                • 2





                  @kappa: Where you could just have operator< and use either std::sort(vec.begin(), vec.end()); or std::sort(vec.rbegin(), vec.rend()); depending on whether you want to have ascending or descending order.

                  – Pixelchemist
                  May 19 '16 at 22:24


















                316














                A simple example using std::sort



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                };

                struct less_than_key
                {
                inline bool operator() (const MyStruct& struct1, const MyStruct& struct2)
                {
                return (struct1.key < struct2.key);
                }
                };

                std::vector < MyStruct > vec;

                vec.push_back(MyStruct(4, "test"));
                vec.push_back(MyStruct(3, "a"));
                vec.push_back(MyStruct(2, "is"));
                vec.push_back(MyStruct(1, "this"));

                std::sort(vec.begin(), vec.end(), less_than_key());




                Edit: As Kirill V. Lyadvinsky pointed out, instead of supplying a sort predicate, you can implement the operator< for MyStruct:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator < (const MyStruct& str) const
                {
                return (key < str.key);
                }
                };


                Using this method means you can simply sort the vector as follows:



                std::sort(vec.begin(), vec.end());


                Edit2: As Kappa suggests you can also sort the vector in the descending order by overloading a > operator and changing call of sort a bit:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator > (const MyStruct& str) const
                {
                return (key > str.key);
                }
                };


                And you should call sort as:



                std::sort(vec.begin(), vec.end(),greater<MyStruct>());





                share|improve this answer





















                • 2





                  Could you explain why you made the compare function in the struct less_than_key (in the first) example inline?

                  – kluka
                  May 15 '13 at 18:10






                • 1





                  and another question/note: if one would like to have multiple sorting methods (for different attributes) in a class the way of overloading the < operator is probably not an option, right?

                  – kluka
                  May 15 '13 at 18:28






                • 5





                  A cool thing is to provide also operator> method. This will allow us to sort in reverse order like: std::sort(vec.begin(), vec.end(), greater<MyStruct>()), which is clean and elegant.

                  – kappa
                  May 30 '14 at 23:21






                • 3





                  @Bovaz You need to #include <functional> to use "std::greater".

                  – Nick Hartung
                  Aug 31 '15 at 15:21








                • 2





                  @kappa: Where you could just have operator< and use either std::sort(vec.begin(), vec.end()); or std::sort(vec.rbegin(), vec.rend()); depending on whether you want to have ascending or descending order.

                  – Pixelchemist
                  May 19 '16 at 22:24
















                316












                316








                316







                A simple example using std::sort



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                };

                struct less_than_key
                {
                inline bool operator() (const MyStruct& struct1, const MyStruct& struct2)
                {
                return (struct1.key < struct2.key);
                }
                };

                std::vector < MyStruct > vec;

                vec.push_back(MyStruct(4, "test"));
                vec.push_back(MyStruct(3, "a"));
                vec.push_back(MyStruct(2, "is"));
                vec.push_back(MyStruct(1, "this"));

                std::sort(vec.begin(), vec.end(), less_than_key());




                Edit: As Kirill V. Lyadvinsky pointed out, instead of supplying a sort predicate, you can implement the operator< for MyStruct:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator < (const MyStruct& str) const
                {
                return (key < str.key);
                }
                };


                Using this method means you can simply sort the vector as follows:



                std::sort(vec.begin(), vec.end());


                Edit2: As Kappa suggests you can also sort the vector in the descending order by overloading a > operator and changing call of sort a bit:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator > (const MyStruct& str) const
                {
                return (key > str.key);
                }
                };


                And you should call sort as:



                std::sort(vec.begin(), vec.end(),greater<MyStruct>());





                share|improve this answer















                A simple example using std::sort



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                };

                struct less_than_key
                {
                inline bool operator() (const MyStruct& struct1, const MyStruct& struct2)
                {
                return (struct1.key < struct2.key);
                }
                };

                std::vector < MyStruct > vec;

                vec.push_back(MyStruct(4, "test"));
                vec.push_back(MyStruct(3, "a"));
                vec.push_back(MyStruct(2, "is"));
                vec.push_back(MyStruct(1, "this"));

                std::sort(vec.begin(), vec.end(), less_than_key());




                Edit: As Kirill V. Lyadvinsky pointed out, instead of supplying a sort predicate, you can implement the operator< for MyStruct:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator < (const MyStruct& str) const
                {
                return (key < str.key);
                }
                };


                Using this method means you can simply sort the vector as follows:



                std::sort(vec.begin(), vec.end());


                Edit2: As Kappa suggests you can also sort the vector in the descending order by overloading a > operator and changing call of sort a bit:



                struct MyStruct
                {
                int key;
                std::string stringValue;

                MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

                bool operator > (const MyStruct& str) const
                {
                return (key > str.key);
                }
                };


                And you should call sort as:



                std::sort(vec.begin(), vec.end(),greater<MyStruct>());






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Mar 26 '18 at 15:30









                Ron

                10.5k21834




                10.5k21834










                answered Sep 4 '09 at 17:12









                AlanAlan

                10.7k83748




                10.7k83748








                • 2





                  Could you explain why you made the compare function in the struct less_than_key (in the first) example inline?

                  – kluka
                  May 15 '13 at 18:10






                • 1





                  and another question/note: if one would like to have multiple sorting methods (for different attributes) in a class the way of overloading the < operator is probably not an option, right?

                  – kluka
                  May 15 '13 at 18:28






                • 5





                  A cool thing is to provide also operator> method. This will allow us to sort in reverse order like: std::sort(vec.begin(), vec.end(), greater<MyStruct>()), which is clean and elegant.

                  – kappa
                  May 30 '14 at 23:21






                • 3





                  @Bovaz You need to #include <functional> to use "std::greater".

                  – Nick Hartung
                  Aug 31 '15 at 15:21








                • 2





                  @kappa: Where you could just have operator< and use either std::sort(vec.begin(), vec.end()); or std::sort(vec.rbegin(), vec.rend()); depending on whether you want to have ascending or descending order.

                  – Pixelchemist
                  May 19 '16 at 22:24
















                • 2





                  Could you explain why you made the compare function in the struct less_than_key (in the first) example inline?

                  – kluka
                  May 15 '13 at 18:10






                • 1





                  and another question/note: if one would like to have multiple sorting methods (for different attributes) in a class the way of overloading the < operator is probably not an option, right?

                  – kluka
                  May 15 '13 at 18:28






                • 5





                  A cool thing is to provide also operator> method. This will allow us to sort in reverse order like: std::sort(vec.begin(), vec.end(), greater<MyStruct>()), which is clean and elegant.

                  – kappa
                  May 30 '14 at 23:21






                • 3





                  @Bovaz You need to #include <functional> to use "std::greater".

                  – Nick Hartung
                  Aug 31 '15 at 15:21








                • 2





                  @kappa: Where you could just have operator< and use either std::sort(vec.begin(), vec.end()); or std::sort(vec.rbegin(), vec.rend()); depending on whether you want to have ascending or descending order.

                  – Pixelchemist
                  May 19 '16 at 22:24










                2




                2





                Could you explain why you made the compare function in the struct less_than_key (in the first) example inline?

                – kluka
                May 15 '13 at 18:10





                Could you explain why you made the compare function in the struct less_than_key (in the first) example inline?

                – kluka
                May 15 '13 at 18:10




                1




                1





                and another question/note: if one would like to have multiple sorting methods (for different attributes) in a class the way of overloading the < operator is probably not an option, right?

                – kluka
                May 15 '13 at 18:28





                and another question/note: if one would like to have multiple sorting methods (for different attributes) in a class the way of overloading the < operator is probably not an option, right?

                – kluka
                May 15 '13 at 18:28




                5




                5





                A cool thing is to provide also operator> method. This will allow us to sort in reverse order like: std::sort(vec.begin(), vec.end(), greater<MyStruct>()), which is clean and elegant.

                – kappa
                May 30 '14 at 23:21





                A cool thing is to provide also operator> method. This will allow us to sort in reverse order like: std::sort(vec.begin(), vec.end(), greater<MyStruct>()), which is clean and elegant.

                – kappa
                May 30 '14 at 23:21




                3




                3





                @Bovaz You need to #include <functional> to use "std::greater".

                – Nick Hartung
                Aug 31 '15 at 15:21







                @Bovaz You need to #include <functional> to use "std::greater".

                – Nick Hartung
                Aug 31 '15 at 15:21






                2




                2





                @kappa: Where you could just have operator< and use either std::sort(vec.begin(), vec.end()); or std::sort(vec.rbegin(), vec.rend()); depending on whether you want to have ascending or descending order.

                – Pixelchemist
                May 19 '16 at 22:24







                @kappa: Where you could just have operator< and use either std::sort(vec.begin(), vec.end()); or std::sort(vec.rbegin(), vec.rend()); depending on whether you want to have ascending or descending order.

                – Pixelchemist
                May 19 '16 at 22:24















                126














                In the interest of coverage. I put forward an implementation using lambda expressions.



                C++11



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
                {
                return lhs.key < rhs.key;
                });


                C++14



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
                {
                return lhs.key < rhs.key;
                });





                share|improve this answer





















                • 13





                  extra +1 for including the #includes

                  – Anne
                  May 3 '16 at 17:35






                • 2





                  To be clear, this results in ascending order; use > instead of < to get descending order.

                  – bhaller
                  Apr 27 '17 at 4:53
















                126














                In the interest of coverage. I put forward an implementation using lambda expressions.



                C++11



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
                {
                return lhs.key < rhs.key;
                });


                C++14



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
                {
                return lhs.key < rhs.key;
                });





                share|improve this answer





















                • 13





                  extra +1 for including the #includes

                  – Anne
                  May 3 '16 at 17:35






                • 2





                  To be clear, this results in ascending order; use > instead of < to get descending order.

                  – bhaller
                  Apr 27 '17 at 4:53














                126












                126








                126







                In the interest of coverage. I put forward an implementation using lambda expressions.



                C++11



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
                {
                return lhs.key < rhs.key;
                });


                C++14



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
                {
                return lhs.key < rhs.key;
                });





                share|improve this answer















                In the interest of coverage. I put forward an implementation using lambda expressions.



                C++11



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
                {
                return lhs.key < rhs.key;
                });


                C++14



                #include <vector>
                #include <algorithm>

                using namespace std;

                vector< MyStruct > values;

                sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
                {
                return lhs.key < rhs.key;
                });






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jul 13 '17 at 22:38

























                answered Oct 10 '14 at 8:54









                CorvusoftCorvusoft

                4,05443468




                4,05443468








                • 13





                  extra +1 for including the #includes

                  – Anne
                  May 3 '16 at 17:35






                • 2





                  To be clear, this results in ascending order; use > instead of < to get descending order.

                  – bhaller
                  Apr 27 '17 at 4:53














                • 13





                  extra +1 for including the #includes

                  – Anne
                  May 3 '16 at 17:35






                • 2





                  To be clear, this results in ascending order; use > instead of < to get descending order.

                  – bhaller
                  Apr 27 '17 at 4:53








                13




                13





                extra +1 for including the #includes

                – Anne
                May 3 '16 at 17:35





                extra +1 for including the #includes

                – Anne
                May 3 '16 at 17:35




                2




                2





                To be clear, this results in ascending order; use > instead of < to get descending order.

                – bhaller
                Apr 27 '17 at 4:53





                To be clear, this results in ascending order; use > instead of < to get descending order.

                – bhaller
                Apr 27 '17 at 4:53











                52














                You could use functor as third argument of std::sort, or you could define operator< in your class.



                struct X {
                int x;
                bool operator<( const X& val ) const {
                return x < val.x;
                }
                };

                struct Xgreater
                {
                bool operator()( const X& lx, const X& rx ) const {
                return lx.x < rx.x;
                }
                };

                int main () {
                std::vector<X> my_vec;

                // use X::operator< by default
                std::sort( my_vec.begin(), my_vec.end() );

                // use functor
                std::sort( my_vec.begin(), my_vec.end(), Xgreater() );
                }





                share|improve this answer





















                • 4





                  why do we need to add const at the end of function signature?

                  – prongs
                  Jun 14 '13 at 11:40






                • 4





                  The function doesn't change the object so it is const.

                  – Kirill V. Lyadvinsky
                  Jul 2 '13 at 8:35











                • If that is the case then why we pass "const X& val", I assume that passing the value as const to a function makes the function think that its value is not going to be changed.

                  – Prashant Bhanarkar
                  Aug 22 '16 at 6:47











                • @PrashantBhanarkar The const keyword at the end of the signature specifies that the operator() function does not change the instance of the Xgreater struct (which in general could have member variables), whereas indicating const for the input values only specifies that those input values are immutable.

                  – schester
                  Dec 28 '17 at 19:35


















                52














                You could use functor as third argument of std::sort, or you could define operator< in your class.



                struct X {
                int x;
                bool operator<( const X& val ) const {
                return x < val.x;
                }
                };

                struct Xgreater
                {
                bool operator()( const X& lx, const X& rx ) const {
                return lx.x < rx.x;
                }
                };

                int main () {
                std::vector<X> my_vec;

                // use X::operator< by default
                std::sort( my_vec.begin(), my_vec.end() );

                // use functor
                std::sort( my_vec.begin(), my_vec.end(), Xgreater() );
                }





                share|improve this answer





















                • 4





                  why do we need to add const at the end of function signature?

                  – prongs
                  Jun 14 '13 at 11:40






                • 4





                  The function doesn't change the object so it is const.

                  – Kirill V. Lyadvinsky
                  Jul 2 '13 at 8:35











                • If that is the case then why we pass "const X& val", I assume that passing the value as const to a function makes the function think that its value is not going to be changed.

                  – Prashant Bhanarkar
                  Aug 22 '16 at 6:47











                • @PrashantBhanarkar The const keyword at the end of the signature specifies that the operator() function does not change the instance of the Xgreater struct (which in general could have member variables), whereas indicating const for the input values only specifies that those input values are immutable.

                  – schester
                  Dec 28 '17 at 19:35
















                52












                52








                52







                You could use functor as third argument of std::sort, or you could define operator< in your class.



                struct X {
                int x;
                bool operator<( const X& val ) const {
                return x < val.x;
                }
                };

                struct Xgreater
                {
                bool operator()( const X& lx, const X& rx ) const {
                return lx.x < rx.x;
                }
                };

                int main () {
                std::vector<X> my_vec;

                // use X::operator< by default
                std::sort( my_vec.begin(), my_vec.end() );

                // use functor
                std::sort( my_vec.begin(), my_vec.end(), Xgreater() );
                }





                share|improve this answer















                You could use functor as third argument of std::sort, or you could define operator< in your class.



                struct X {
                int x;
                bool operator<( const X& val ) const {
                return x < val.x;
                }
                };

                struct Xgreater
                {
                bool operator()( const X& lx, const X& rx ) const {
                return lx.x < rx.x;
                }
                };

                int main () {
                std::vector<X> my_vec;

                // use X::operator< by default
                std::sort( my_vec.begin(), my_vec.end() );

                // use functor
                std::sort( my_vec.begin(), my_vec.end(), Xgreater() );
                }






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 4 '09 at 17:16

























                answered Sep 4 '09 at 17:08









                Kirill V. LyadvinskyKirill V. Lyadvinsky

                77.8k19117204




                77.8k19117204








                • 4





                  why do we need to add const at the end of function signature?

                  – prongs
                  Jun 14 '13 at 11:40






                • 4





                  The function doesn't change the object so it is const.

                  – Kirill V. Lyadvinsky
                  Jul 2 '13 at 8:35











                • If that is the case then why we pass "const X& val", I assume that passing the value as const to a function makes the function think that its value is not going to be changed.

                  – Prashant Bhanarkar
                  Aug 22 '16 at 6:47











                • @PrashantBhanarkar The const keyword at the end of the signature specifies that the operator() function does not change the instance of the Xgreater struct (which in general could have member variables), whereas indicating const for the input values only specifies that those input values are immutable.

                  – schester
                  Dec 28 '17 at 19:35
















                • 4





                  why do we need to add const at the end of function signature?

                  – prongs
                  Jun 14 '13 at 11:40






                • 4





                  The function doesn't change the object so it is const.

                  – Kirill V. Lyadvinsky
                  Jul 2 '13 at 8:35











                • If that is the case then why we pass "const X& val", I assume that passing the value as const to a function makes the function think that its value is not going to be changed.

                  – Prashant Bhanarkar
                  Aug 22 '16 at 6:47











                • @PrashantBhanarkar The const keyword at the end of the signature specifies that the operator() function does not change the instance of the Xgreater struct (which in general could have member variables), whereas indicating const for the input values only specifies that those input values are immutable.

                  – schester
                  Dec 28 '17 at 19:35










                4




                4





                why do we need to add const at the end of function signature?

                – prongs
                Jun 14 '13 at 11:40





                why do we need to add const at the end of function signature?

                – prongs
                Jun 14 '13 at 11:40




                4




                4





                The function doesn't change the object so it is const.

                – Kirill V. Lyadvinsky
                Jul 2 '13 at 8:35





                The function doesn't change the object so it is const.

                – Kirill V. Lyadvinsky
                Jul 2 '13 at 8:35













                If that is the case then why we pass "const X& val", I assume that passing the value as const to a function makes the function think that its value is not going to be changed.

                – Prashant Bhanarkar
                Aug 22 '16 at 6:47





                If that is the case then why we pass "const X& val", I assume that passing the value as const to a function makes the function think that its value is not going to be changed.

                – Prashant Bhanarkar
                Aug 22 '16 at 6:47













                @PrashantBhanarkar The const keyword at the end of the signature specifies that the operator() function does not change the instance of the Xgreater struct (which in general could have member variables), whereas indicating const for the input values only specifies that those input values are immutable.

                – schester
                Dec 28 '17 at 19:35







                @PrashantBhanarkar The const keyword at the end of the signature specifies that the operator() function does not change the instance of the Xgreater struct (which in general could have member variables), whereas indicating const for the input values only specifies that those input values are immutable.

                – schester
                Dec 28 '17 at 19:35













                13














                You are on the right track. std::sort will use operator< as comparison function by default. So in order to sort your objects, you will either have to overload bool operator<( const T&, const T& ) or provide a functor that does the comparison, much like this:



                 struct C {
                int i;
                static bool before( const C& c1, const C& c2 ) { return c1.i < c2.i; }
                };

                bool operator<( const C& c1, const C& c2 ) { return c1.i > c2.i; }

                std::vector<C> values;

                std::sort( values.begin(), values.end() ); // uses operator<
                std::sort( values.begin(), values.end(), C::before );


                The advantage of the usage of a functor is that you can use a function with access to the class' private members.






                share|improve this answer


























                • Missed that one: provide a member function operator<.

                  – xtofl
                  Sep 4 '09 at 17:13






                • 1





                  It is better to make operator< a member of class (or struct), because global one could use protected or private members. Or you should make it a friend of struct C.

                  – Kirill V. Lyadvinsky
                  Sep 4 '09 at 17:25
















                13














                You are on the right track. std::sort will use operator< as comparison function by default. So in order to sort your objects, you will either have to overload bool operator<( const T&, const T& ) or provide a functor that does the comparison, much like this:



                 struct C {
                int i;
                static bool before( const C& c1, const C& c2 ) { return c1.i < c2.i; }
                };

                bool operator<( const C& c1, const C& c2 ) { return c1.i > c2.i; }

                std::vector<C> values;

                std::sort( values.begin(), values.end() ); // uses operator<
                std::sort( values.begin(), values.end(), C::before );


                The advantage of the usage of a functor is that you can use a function with access to the class' private members.






                share|improve this answer


























                • Missed that one: provide a member function operator<.

                  – xtofl
                  Sep 4 '09 at 17:13






                • 1





                  It is better to make operator< a member of class (or struct), because global one could use protected or private members. Or you should make it a friend of struct C.

                  – Kirill V. Lyadvinsky
                  Sep 4 '09 at 17:25














                13












                13








                13







                You are on the right track. std::sort will use operator< as comparison function by default. So in order to sort your objects, you will either have to overload bool operator<( const T&, const T& ) or provide a functor that does the comparison, much like this:



                 struct C {
                int i;
                static bool before( const C& c1, const C& c2 ) { return c1.i < c2.i; }
                };

                bool operator<( const C& c1, const C& c2 ) { return c1.i > c2.i; }

                std::vector<C> values;

                std::sort( values.begin(), values.end() ); // uses operator<
                std::sort( values.begin(), values.end(), C::before );


                The advantage of the usage of a functor is that you can use a function with access to the class' private members.






                share|improve this answer















                You are on the right track. std::sort will use operator< as comparison function by default. So in order to sort your objects, you will either have to overload bool operator<( const T&, const T& ) or provide a functor that does the comparison, much like this:



                 struct C {
                int i;
                static bool before( const C& c1, const C& c2 ) { return c1.i < c2.i; }
                };

                bool operator<( const C& c1, const C& c2 ) { return c1.i > c2.i; }

                std::vector<C> values;

                std::sort( values.begin(), values.end() ); // uses operator<
                std::sort( values.begin(), values.end(), C::before );


                The advantage of the usage of a functor is that you can use a function with access to the class' private members.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Mar 1 '16 at 21:32









                pjvandehaar

                683721




                683721










                answered Sep 4 '09 at 17:10









                xtoflxtofl

                31.7k681160




                31.7k681160













                • Missed that one: provide a member function operator<.

                  – xtofl
                  Sep 4 '09 at 17:13






                • 1





                  It is better to make operator< a member of class (or struct), because global one could use protected or private members. Or you should make it a friend of struct C.

                  – Kirill V. Lyadvinsky
                  Sep 4 '09 at 17:25



















                • Missed that one: provide a member function operator<.

                  – xtofl
                  Sep 4 '09 at 17:13






                • 1





                  It is better to make operator< a member of class (or struct), because global one could use protected or private members. Or you should make it a friend of struct C.

                  – Kirill V. Lyadvinsky
                  Sep 4 '09 at 17:25

















                Missed that one: provide a member function operator<.

                – xtofl
                Sep 4 '09 at 17:13





                Missed that one: provide a member function operator<.

                – xtofl
                Sep 4 '09 at 17:13




                1




                1





                It is better to make operator< a member of class (or struct), because global one could use protected or private members. Or you should make it a friend of struct C.

                – Kirill V. Lyadvinsky
                Sep 4 '09 at 17:25





                It is better to make operator< a member of class (or struct), because global one could use protected or private members. Or you should make it a friend of struct C.

                – Kirill V. Lyadvinsky
                Sep 4 '09 at 17:25











                11














                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





                • sort,


                • stable_sort,


                • partial_sort or


                • partial_sort_copy.


                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));





                share|improve this answer


























                • In 2. case you wrote bool X_less(X const &l, X const &r) const { return l.i < r.i; } for comparator but the const keywords should be removed (as it's not a member function).

                  – PolGraphic
                  Aug 29 '16 at 17:43











                • @PolGraphic: Correct - in case 1 as well.

                  – Pixelchemist
                  Aug 29 '16 at 21:45











                • @Pixelchemist how would I use the (4.) lambda approach when not using std::sort or similar, but needed an instance of Compare, e.g. when instantiating a std::set ?

                  – azrdev
                  Mar 28 '18 at 13:56






                • 1





                  @azrdev: A function template that capture the type of the closure to pass it as a template parameter to set: template<class T, class C> std::set<T, C> make_set(C const& compare) { return std::set<T, C>{ compare }; } which could be used like auto xset = make_set<X>((auto && l, auto && r) { return l.i < r.i; });.

                  – Pixelchemist
                  Mar 29 '18 at 19:19
















                11














                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





                • sort,


                • stable_sort,


                • partial_sort or


                • partial_sort_copy.


                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));





                share|improve this answer


























                • In 2. case you wrote bool X_less(X const &l, X const &r) const { return l.i < r.i; } for comparator but the const keywords should be removed (as it's not a member function).

                  – PolGraphic
                  Aug 29 '16 at 17:43











                • @PolGraphic: Correct - in case 1 as well.

                  – Pixelchemist
                  Aug 29 '16 at 21:45











                • @Pixelchemist how would I use the (4.) lambda approach when not using std::sort or similar, but needed an instance of Compare, e.g. when instantiating a std::set ?

                  – azrdev
                  Mar 28 '18 at 13:56






                • 1





                  @azrdev: A function template that capture the type of the closure to pass it as a template parameter to set: template<class T, class C> std::set<T, C> make_set(C const& compare) { return std::set<T, C>{ compare }; } which could be used like auto xset = make_set<X>((auto && l, auto && r) { return l.i < r.i; });.

                  – Pixelchemist
                  Mar 29 '18 at 19:19














                11












                11








                11







                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





                • sort,


                • stable_sort,


                • partial_sort or


                • partial_sort_copy.


                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));





                share|improve this answer















                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





                • sort,


                • stable_sort,


                • partial_sort or


                • partial_sort_copy.


                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));






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Aug 29 '16 at 21:44

























                answered May 19 '16 at 22:11









                PixelchemistPixelchemist

                16.4k43262




                16.4k43262













                • In 2. case you wrote bool X_less(X const &l, X const &r) const { return l.i < r.i; } for comparator but the const keywords should be removed (as it's not a member function).

                  – PolGraphic
                  Aug 29 '16 at 17:43











                • @PolGraphic: Correct - in case 1 as well.

                  – Pixelchemist
                  Aug 29 '16 at 21:45











                • @Pixelchemist how would I use the (4.) lambda approach when not using std::sort or similar, but needed an instance of Compare, e.g. when instantiating a std::set ?

                  – azrdev
                  Mar 28 '18 at 13:56






                • 1





                  @azrdev: A function template that capture the type of the closure to pass it as a template parameter to set: template<class T, class C> std::set<T, C> make_set(C const& compare) { return std::set<T, C>{ compare }; } which could be used like auto xset = make_set<X>((auto && l, auto && r) { return l.i < r.i; });.

                  – Pixelchemist
                  Mar 29 '18 at 19:19



















                • In 2. case you wrote bool X_less(X const &l, X const &r) const { return l.i < r.i; } for comparator but the const keywords should be removed (as it's not a member function).

                  – PolGraphic
                  Aug 29 '16 at 17:43











                • @PolGraphic: Correct - in case 1 as well.

                  – Pixelchemist
                  Aug 29 '16 at 21:45











                • @Pixelchemist how would I use the (4.) lambda approach when not using std::sort or similar, but needed an instance of Compare, e.g. when instantiating a std::set ?

                  – azrdev
                  Mar 28 '18 at 13:56






                • 1





                  @azrdev: A function template that capture the type of the closure to pass it as a template parameter to set: template<class T, class C> std::set<T, C> make_set(C const& compare) { return std::set<T, C>{ compare }; } which could be used like auto xset = make_set<X>((auto && l, auto && r) { return l.i < r.i; });.

                  – Pixelchemist
                  Mar 29 '18 at 19:19

















                In 2. case you wrote bool X_less(X const &l, X const &r) const { return l.i < r.i; } for comparator but the const keywords should be removed (as it's not a member function).

                – PolGraphic
                Aug 29 '16 at 17:43





                In 2. case you wrote bool X_less(X const &l, X const &r) const { return l.i < r.i; } for comparator but the const keywords should be removed (as it's not a member function).

                – PolGraphic
                Aug 29 '16 at 17:43













                @PolGraphic: Correct - in case 1 as well.

                – Pixelchemist
                Aug 29 '16 at 21:45





                @PolGraphic: Correct - in case 1 as well.

                – Pixelchemist
                Aug 29 '16 at 21:45













                @Pixelchemist how would I use the (4.) lambda approach when not using std::sort or similar, but needed an instance of Compare, e.g. when instantiating a std::set ?

                – azrdev
                Mar 28 '18 at 13:56





                @Pixelchemist how would I use the (4.) lambda approach when not using std::sort or similar, but needed an instance of Compare, e.g. when instantiating a std::set ?

                – azrdev
                Mar 28 '18 at 13:56




                1




                1





                @azrdev: A function template that capture the type of the closure to pass it as a template parameter to set: template<class T, class C> std::set<T, C> make_set(C const& compare) { return std::set<T, C>{ compare }; } which could be used like auto xset = make_set<X>((auto && l, auto && r) { return l.i < r.i; });.

                – Pixelchemist
                Mar 29 '18 at 19:19





                @azrdev: A function template that capture the type of the closure to pass it as a template parameter to set: template<class T, class C> std::set<T, C> make_set(C const& compare) { return std::set<T, C>{ compare }; } which could be used like auto xset = make_set<X>((auto && l, auto && r) { return l.i < r.i; });.

                – Pixelchemist
                Mar 29 '18 at 19:19











                4














                Yes, std::sort() with third parameter (function or object) would be easier. An example:
                http://www.cplusplus.com/reference/algorithm/sort/






                share|improve this answer


























                • Not exactly a link only answer but at least a single line example would be useful.

                  – Manos Nikolaidis
                  Dec 31 '15 at 11:20
















                4














                Yes, std::sort() with third parameter (function or object) would be easier. An example:
                http://www.cplusplus.com/reference/algorithm/sort/






                share|improve this answer


























                • Not exactly a link only answer but at least a single line example would be useful.

                  – Manos Nikolaidis
                  Dec 31 '15 at 11:20














                4












                4








                4







                Yes, std::sort() with third parameter (function or object) would be easier. An example:
                http://www.cplusplus.com/reference/algorithm/sort/






                share|improve this answer















                Yes, std::sort() with third parameter (function or object) would be easier. An example:
                http://www.cplusplus.com/reference/algorithm/sort/







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 31 '15 at 11:20









                Manos Nikolaidis

                15k104560




                15k104560










                answered Sep 4 '09 at 17:11









                swatkatswatkat

                3,7521916




                3,7521916













                • Not exactly a link only answer but at least a single line example would be useful.

                  – Manos Nikolaidis
                  Dec 31 '15 at 11:20



















                • Not exactly a link only answer but at least a single line example would be useful.

                  – Manos Nikolaidis
                  Dec 31 '15 at 11:20

















                Not exactly a link only answer but at least a single line example would be useful.

                – Manos Nikolaidis
                Dec 31 '15 at 11:20





                Not exactly a link only answer but at least a single line example would be useful.

                – Manos Nikolaidis
                Dec 31 '15 at 11:20











                3














                In your class, you may overload the "<" operator.



                class MyClass
                {
                bool operator <(const MyClass& rhs)
                {
                return this->key < rhs.key;
                }
                }





                share|improve this answer






























                  3














                  In your class, you may overload the "<" operator.



                  class MyClass
                  {
                  bool operator <(const MyClass& rhs)
                  {
                  return this->key < rhs.key;
                  }
                  }





                  share|improve this answer




























                    3












                    3








                    3







                    In your class, you may overload the "<" operator.



                    class MyClass
                    {
                    bool operator <(const MyClass& rhs)
                    {
                    return this->key < rhs.key;
                    }
                    }





                    share|improve this answer















                    In your class, you may overload the "<" operator.



                    class MyClass
                    {
                    bool operator <(const MyClass& rhs)
                    {
                    return this->key < rhs.key;
                    }
                    }






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Oct 10 '14 at 18:52









                    Corvusoft

                    4,05443468




                    4,05443468










                    answered Sep 4 '09 at 17:10









                    BobbyShaftoeBobbyShaftoe

                    23.8k54770




                    23.8k54770























                        2














                        Below is the code using lambdas



                        #include "stdafx.h"
                        #include <vector>
                        #include <algorithm>

                        using namespace std;

                        struct MyStruct
                        {
                        int key;
                        std::string stringValue;

                        MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                        };

                        int main()
                        {
                        std::vector < MyStruct > vec;

                        vec.push_back(MyStruct(4, "test"));
                        vec.push_back(MyStruct(3, "a"));
                        vec.push_back(MyStruct(2, "is"));
                        vec.push_back(MyStruct(1, "this"));

                        std::sort(vec.begin(), vec.end(),
                        (const MyStruct& struct1, const MyStruct& struct2)
                        {
                        return (struct1.key < struct2.key);
                        }
                        );
                        return 0;
                        }





                        share|improve this answer




























                          2














                          Below is the code using lambdas



                          #include "stdafx.h"
                          #include <vector>
                          #include <algorithm>

                          using namespace std;

                          struct MyStruct
                          {
                          int key;
                          std::string stringValue;

                          MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                          };

                          int main()
                          {
                          std::vector < MyStruct > vec;

                          vec.push_back(MyStruct(4, "test"));
                          vec.push_back(MyStruct(3, "a"));
                          vec.push_back(MyStruct(2, "is"));
                          vec.push_back(MyStruct(1, "this"));

                          std::sort(vec.begin(), vec.end(),
                          (const MyStruct& struct1, const MyStruct& struct2)
                          {
                          return (struct1.key < struct2.key);
                          }
                          );
                          return 0;
                          }





                          share|improve this answer


























                            2












                            2








                            2







                            Below is the code using lambdas



                            #include "stdafx.h"
                            #include <vector>
                            #include <algorithm>

                            using namespace std;

                            struct MyStruct
                            {
                            int key;
                            std::string stringValue;

                            MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                            };

                            int main()
                            {
                            std::vector < MyStruct > vec;

                            vec.push_back(MyStruct(4, "test"));
                            vec.push_back(MyStruct(3, "a"));
                            vec.push_back(MyStruct(2, "is"));
                            vec.push_back(MyStruct(1, "this"));

                            std::sort(vec.begin(), vec.end(),
                            (const MyStruct& struct1, const MyStruct& struct2)
                            {
                            return (struct1.key < struct2.key);
                            }
                            );
                            return 0;
                            }





                            share|improve this answer













                            Below is the code using lambdas



                            #include "stdafx.h"
                            #include <vector>
                            #include <algorithm>

                            using namespace std;

                            struct MyStruct
                            {
                            int key;
                            std::string stringValue;

                            MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}
                            };

                            int main()
                            {
                            std::vector < MyStruct > vec;

                            vec.push_back(MyStruct(4, "test"));
                            vec.push_back(MyStruct(3, "a"));
                            vec.push_back(MyStruct(2, "is"));
                            vec.push_back(MyStruct(1, "this"));

                            std::sort(vec.begin(), vec.end(),
                            (const MyStruct& struct1, const MyStruct& struct2)
                            {
                            return (struct1.key < struct2.key);
                            }
                            );
                            return 0;
                            }






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Apr 20 '16 at 7:28









                            SathwickSathwick

                            4426




                            4426























                                2














                                I was curious if there is any measurable impact on performance between the various ways one can call std::sort, so I've created this simple test:



                                $ cat sort.cpp
                                #include<algorithm>
                                #include<iostream>
                                #include<vector>
                                #include<chrono>

                                #define COMPILER_BARRIER() asm volatile("" ::: "memory");

                                typedef unsigned long int ulint;

                                using namespace std;

                                struct S {
                                int x;
                                int y;
                                };

                                #define BODY { return s1.x*s2.y < s2.x*s1.y; }

                                bool operator<( const S& s1, const S& s2 ) BODY
                                bool Sgreater_func( const S& s1, const S& s2 ) BODY

                                struct Sgreater {
                                bool operator()( const S& s1, const S& s2 ) const BODY
                                };

                                void sort_by_operator(vector<S> & v){
                                sort(v.begin(), v.end());
                                }

                                void sort_by_lambda(vector<S> & v){
                                sort(v.begin(), v.end(), ( const S& s1, const S& s2 ) BODY );
                                }

                                void sort_by_functor(vector<S> &v){
                                sort(v.begin(), v.end(), Sgreater());
                                }

                                void sort_by_function(vector<S> &v){
                                sort(v.begin(), v.end(), &Sgreater_func);
                                }

                                const int N = 10000000;
                                vector<S> random_vector;

                                ulint run(void foo(vector<S> &v)){
                                vector<S> tmp(random_vector);
                                foo(tmp);
                                ulint checksum = 0;
                                for(int i=0;i<tmp.size();++i){
                                checksum += i *tmp[i].x ^ tmp[i].y;
                                }
                                return checksum;
                                }

                                void measure(void foo(vector<S> & v)){

                                ulint check_sum = 0;

                                // warm up
                                const int WARMUP_ROUNDS = 3;
                                const int TEST_ROUNDS = 10;

                                for(int t=WARMUP_ROUNDS;t--;){
                                COMPILER_BARRIER();
                                check_sum += run(foo);
                                COMPILER_BARRIER();
                                }

                                for(int t=TEST_ROUNDS;t--;){
                                COMPILER_BARRIER();
                                auto start = std::chrono::high_resolution_clock::now();
                                COMPILER_BARRIER();
                                check_sum += run(foo);
                                COMPILER_BARRIER();
                                auto end = std::chrono::high_resolution_clock::now();
                                COMPILER_BARRIER();
                                auto duration_ns = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();

                                cout << "Took " << duration_ns << "s to complete round" << endl;
                                }

                                cout << "Checksum: " << check_sum << endl;
                                }

                                #define M(x)
                                cout << "Measure " #x " on " << N << " items:" << endl;
                                measure(x);

                                int main(){
                                random_vector.reserve(N);

                                for(int i=0;i<N;++i){
                                random_vector.push_back(S{rand(), rand()});
                                }

                                M(sort_by_operator);
                                M(sort_by_lambda);
                                M(sort_by_functor);
                                M(sort_by_function);
                                return 0;
                                }


                                What it does is it creates a random vector, and then measures how much time is required to copy it and sort the copy of it (and compute some checksum to avoid too vigorous dead code elimination).



                                I was compiling with g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)



                                $ g++ -O2 -o sort sort.cpp && ./sort


                                Here are results:



                                Measure sort_by_operator on 10000000 items:
                                Took 0.994285s to complete round
                                Took 0.990162s to complete round
                                Took 0.992103s to complete round
                                Took 0.989638s to complete round
                                Took 0.98105s to complete round
                                Took 0.991913s to complete round
                                Took 0.992176s to complete round
                                Took 0.981706s to complete round
                                Took 0.99021s to complete round
                                Took 0.988841s to complete round
                                Checksum: 18446656212269526361
                                Measure sort_by_lambda on 10000000 items:
                                Took 0.974274s to complete round
                                Took 0.97298s to complete round
                                Took 0.964506s to complete round
                                Took 0.96899s to complete round
                                Took 0.965773s to complete round
                                Took 0.96457s to complete round
                                Took 0.974286s to complete round
                                Took 0.975524s to complete round
                                Took 0.966238s to complete round
                                Took 0.964676s to complete round
                                Checksum: 18446656212269526361
                                Measure sort_by_functor on 10000000 items:
                                Took 0.964359s to complete round
                                Took 0.979619s to complete round
                                Took 0.974027s to complete round
                                Took 0.964671s to complete round
                                Took 0.964764s to complete round
                                Took 0.966491s to complete round
                                Took 0.964706s to complete round
                                Took 0.965115s to complete round
                                Took 0.964352s to complete round
                                Took 0.968954s to complete round
                                Checksum: 18446656212269526361
                                Measure sort_by_function on 10000000 items:
                                Took 1.29942s to complete round
                                Took 1.3029s to complete round
                                Took 1.29931s to complete round
                                Took 1.29946s to complete round
                                Took 1.29837s to complete round
                                Took 1.30132s to complete round
                                Took 1.3023s to complete round
                                Took 1.30997s to complete round
                                Took 1.30819s to complete round
                                Took 1.3003s to complete round
                                Checksum: 18446656212269526361


                                Looks like all the options except for passing function pointer are very similar, and passing a function pointer causes +30% penalty.



                                It also looks like the operator< version is ~1% slower (I repeated the test multiple times and the effect persists), which is a bit strange as it suggests that the generated code is different (I lack skill to analyze --save-temps output).






                                share|improve this answer






























                                  2














                                  I was curious if there is any measurable impact on performance between the various ways one can call std::sort, so I've created this simple test:



                                  $ cat sort.cpp
                                  #include<algorithm>
                                  #include<iostream>
                                  #include<vector>
                                  #include<chrono>

                                  #define COMPILER_BARRIER() asm volatile("" ::: "memory");

                                  typedef unsigned long int ulint;

                                  using namespace std;

                                  struct S {
                                  int x;
                                  int y;
                                  };

                                  #define BODY { return s1.x*s2.y < s2.x*s1.y; }

                                  bool operator<( const S& s1, const S& s2 ) BODY
                                  bool Sgreater_func( const S& s1, const S& s2 ) BODY

                                  struct Sgreater {
                                  bool operator()( const S& s1, const S& s2 ) const BODY
                                  };

                                  void sort_by_operator(vector<S> & v){
                                  sort(v.begin(), v.end());
                                  }

                                  void sort_by_lambda(vector<S> & v){
                                  sort(v.begin(), v.end(), ( const S& s1, const S& s2 ) BODY );
                                  }

                                  void sort_by_functor(vector<S> &v){
                                  sort(v.begin(), v.end(), Sgreater());
                                  }

                                  void sort_by_function(vector<S> &v){
                                  sort(v.begin(), v.end(), &Sgreater_func);
                                  }

                                  const int N = 10000000;
                                  vector<S> random_vector;

                                  ulint run(void foo(vector<S> &v)){
                                  vector<S> tmp(random_vector);
                                  foo(tmp);
                                  ulint checksum = 0;
                                  for(int i=0;i<tmp.size();++i){
                                  checksum += i *tmp[i].x ^ tmp[i].y;
                                  }
                                  return checksum;
                                  }

                                  void measure(void foo(vector<S> & v)){

                                  ulint check_sum = 0;

                                  // warm up
                                  const int WARMUP_ROUNDS = 3;
                                  const int TEST_ROUNDS = 10;

                                  for(int t=WARMUP_ROUNDS;t--;){
                                  COMPILER_BARRIER();
                                  check_sum += run(foo);
                                  COMPILER_BARRIER();
                                  }

                                  for(int t=TEST_ROUNDS;t--;){
                                  COMPILER_BARRIER();
                                  auto start = std::chrono::high_resolution_clock::now();
                                  COMPILER_BARRIER();
                                  check_sum += run(foo);
                                  COMPILER_BARRIER();
                                  auto end = std::chrono::high_resolution_clock::now();
                                  COMPILER_BARRIER();
                                  auto duration_ns = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();

                                  cout << "Took " << duration_ns << "s to complete round" << endl;
                                  }

                                  cout << "Checksum: " << check_sum << endl;
                                  }

                                  #define M(x)
                                  cout << "Measure " #x " on " << N << " items:" << endl;
                                  measure(x);

                                  int main(){
                                  random_vector.reserve(N);

                                  for(int i=0;i<N;++i){
                                  random_vector.push_back(S{rand(), rand()});
                                  }

                                  M(sort_by_operator);
                                  M(sort_by_lambda);
                                  M(sort_by_functor);
                                  M(sort_by_function);
                                  return 0;
                                  }


                                  What it does is it creates a random vector, and then measures how much time is required to copy it and sort the copy of it (and compute some checksum to avoid too vigorous dead code elimination).



                                  I was compiling with g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)



                                  $ g++ -O2 -o sort sort.cpp && ./sort


                                  Here are results:



                                  Measure sort_by_operator on 10000000 items:
                                  Took 0.994285s to complete round
                                  Took 0.990162s to complete round
                                  Took 0.992103s to complete round
                                  Took 0.989638s to complete round
                                  Took 0.98105s to complete round
                                  Took 0.991913s to complete round
                                  Took 0.992176s to complete round
                                  Took 0.981706s to complete round
                                  Took 0.99021s to complete round
                                  Took 0.988841s to complete round
                                  Checksum: 18446656212269526361
                                  Measure sort_by_lambda on 10000000 items:
                                  Took 0.974274s to complete round
                                  Took 0.97298s to complete round
                                  Took 0.964506s to complete round
                                  Took 0.96899s to complete round
                                  Took 0.965773s to complete round
                                  Took 0.96457s to complete round
                                  Took 0.974286s to complete round
                                  Took 0.975524s to complete round
                                  Took 0.966238s to complete round
                                  Took 0.964676s to complete round
                                  Checksum: 18446656212269526361
                                  Measure sort_by_functor on 10000000 items:
                                  Took 0.964359s to complete round
                                  Took 0.979619s to complete round
                                  Took 0.974027s to complete round
                                  Took 0.964671s to complete round
                                  Took 0.964764s to complete round
                                  Took 0.966491s to complete round
                                  Took 0.964706s to complete round
                                  Took 0.965115s to complete round
                                  Took 0.964352s to complete round
                                  Took 0.968954s to complete round
                                  Checksum: 18446656212269526361
                                  Measure sort_by_function on 10000000 items:
                                  Took 1.29942s to complete round
                                  Took 1.3029s to complete round
                                  Took 1.29931s to complete round
                                  Took 1.29946s to complete round
                                  Took 1.29837s to complete round
                                  Took 1.30132s to complete round
                                  Took 1.3023s to complete round
                                  Took 1.30997s to complete round
                                  Took 1.30819s to complete round
                                  Took 1.3003s to complete round
                                  Checksum: 18446656212269526361


                                  Looks like all the options except for passing function pointer are very similar, and passing a function pointer causes +30% penalty.



                                  It also looks like the operator< version is ~1% slower (I repeated the test multiple times and the effect persists), which is a bit strange as it suggests that the generated code is different (I lack skill to analyze --save-temps output).






                                  share|improve this answer




























                                    2












                                    2








                                    2







                                    I was curious if there is any measurable impact on performance between the various ways one can call std::sort, so I've created this simple test:



                                    $ cat sort.cpp
                                    #include<algorithm>
                                    #include<iostream>
                                    #include<vector>
                                    #include<chrono>

                                    #define COMPILER_BARRIER() asm volatile("" ::: "memory");

                                    typedef unsigned long int ulint;

                                    using namespace std;

                                    struct S {
                                    int x;
                                    int y;
                                    };

                                    #define BODY { return s1.x*s2.y < s2.x*s1.y; }

                                    bool operator<( const S& s1, const S& s2 ) BODY
                                    bool Sgreater_func( const S& s1, const S& s2 ) BODY

                                    struct Sgreater {
                                    bool operator()( const S& s1, const S& s2 ) const BODY
                                    };

                                    void sort_by_operator(vector<S> & v){
                                    sort(v.begin(), v.end());
                                    }

                                    void sort_by_lambda(vector<S> & v){
                                    sort(v.begin(), v.end(), ( const S& s1, const S& s2 ) BODY );
                                    }

                                    void sort_by_functor(vector<S> &v){
                                    sort(v.begin(), v.end(), Sgreater());
                                    }

                                    void sort_by_function(vector<S> &v){
                                    sort(v.begin(), v.end(), &Sgreater_func);
                                    }

                                    const int N = 10000000;
                                    vector<S> random_vector;

                                    ulint run(void foo(vector<S> &v)){
                                    vector<S> tmp(random_vector);
                                    foo(tmp);
                                    ulint checksum = 0;
                                    for(int i=0;i<tmp.size();++i){
                                    checksum += i *tmp[i].x ^ tmp[i].y;
                                    }
                                    return checksum;
                                    }

                                    void measure(void foo(vector<S> & v)){

                                    ulint check_sum = 0;

                                    // warm up
                                    const int WARMUP_ROUNDS = 3;
                                    const int TEST_ROUNDS = 10;

                                    for(int t=WARMUP_ROUNDS;t--;){
                                    COMPILER_BARRIER();
                                    check_sum += run(foo);
                                    COMPILER_BARRIER();
                                    }

                                    for(int t=TEST_ROUNDS;t--;){
                                    COMPILER_BARRIER();
                                    auto start = std::chrono::high_resolution_clock::now();
                                    COMPILER_BARRIER();
                                    check_sum += run(foo);
                                    COMPILER_BARRIER();
                                    auto end = std::chrono::high_resolution_clock::now();
                                    COMPILER_BARRIER();
                                    auto duration_ns = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();

                                    cout << "Took " << duration_ns << "s to complete round" << endl;
                                    }

                                    cout << "Checksum: " << check_sum << endl;
                                    }

                                    #define M(x)
                                    cout << "Measure " #x " on " << N << " items:" << endl;
                                    measure(x);

                                    int main(){
                                    random_vector.reserve(N);

                                    for(int i=0;i<N;++i){
                                    random_vector.push_back(S{rand(), rand()});
                                    }

                                    M(sort_by_operator);
                                    M(sort_by_lambda);
                                    M(sort_by_functor);
                                    M(sort_by_function);
                                    return 0;
                                    }


                                    What it does is it creates a random vector, and then measures how much time is required to copy it and sort the copy of it (and compute some checksum to avoid too vigorous dead code elimination).



                                    I was compiling with g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)



                                    $ g++ -O2 -o sort sort.cpp && ./sort


                                    Here are results:



                                    Measure sort_by_operator on 10000000 items:
                                    Took 0.994285s to complete round
                                    Took 0.990162s to complete round
                                    Took 0.992103s to complete round
                                    Took 0.989638s to complete round
                                    Took 0.98105s to complete round
                                    Took 0.991913s to complete round
                                    Took 0.992176s to complete round
                                    Took 0.981706s to complete round
                                    Took 0.99021s to complete round
                                    Took 0.988841s to complete round
                                    Checksum: 18446656212269526361
                                    Measure sort_by_lambda on 10000000 items:
                                    Took 0.974274s to complete round
                                    Took 0.97298s to complete round
                                    Took 0.964506s to complete round
                                    Took 0.96899s to complete round
                                    Took 0.965773s to complete round
                                    Took 0.96457s to complete round
                                    Took 0.974286s to complete round
                                    Took 0.975524s to complete round
                                    Took 0.966238s to complete round
                                    Took 0.964676s to complete round
                                    Checksum: 18446656212269526361
                                    Measure sort_by_functor on 10000000 items:
                                    Took 0.964359s to complete round
                                    Took 0.979619s to complete round
                                    Took 0.974027s to complete round
                                    Took 0.964671s to complete round
                                    Took 0.964764s to complete round
                                    Took 0.966491s to complete round
                                    Took 0.964706s to complete round
                                    Took 0.965115s to complete round
                                    Took 0.964352s to complete round
                                    Took 0.968954s to complete round
                                    Checksum: 18446656212269526361
                                    Measure sort_by_function on 10000000 items:
                                    Took 1.29942s to complete round
                                    Took 1.3029s to complete round
                                    Took 1.29931s to complete round
                                    Took 1.29946s to complete round
                                    Took 1.29837s to complete round
                                    Took 1.30132s to complete round
                                    Took 1.3023s to complete round
                                    Took 1.30997s to complete round
                                    Took 1.30819s to complete round
                                    Took 1.3003s to complete round
                                    Checksum: 18446656212269526361


                                    Looks like all the options except for passing function pointer are very similar, and passing a function pointer causes +30% penalty.



                                    It also looks like the operator< version is ~1% slower (I repeated the test multiple times and the effect persists), which is a bit strange as it suggests that the generated code is different (I lack skill to analyze --save-temps output).






                                    share|improve this answer















                                    I was curious if there is any measurable impact on performance between the various ways one can call std::sort, so I've created this simple test:



                                    $ cat sort.cpp
                                    #include<algorithm>
                                    #include<iostream>
                                    #include<vector>
                                    #include<chrono>

                                    #define COMPILER_BARRIER() asm volatile("" ::: "memory");

                                    typedef unsigned long int ulint;

                                    using namespace std;

                                    struct S {
                                    int x;
                                    int y;
                                    };

                                    #define BODY { return s1.x*s2.y < s2.x*s1.y; }

                                    bool operator<( const S& s1, const S& s2 ) BODY
                                    bool Sgreater_func( const S& s1, const S& s2 ) BODY

                                    struct Sgreater {
                                    bool operator()( const S& s1, const S& s2 ) const BODY
                                    };

                                    void sort_by_operator(vector<S> & v){
                                    sort(v.begin(), v.end());
                                    }

                                    void sort_by_lambda(vector<S> & v){
                                    sort(v.begin(), v.end(), ( const S& s1, const S& s2 ) BODY );
                                    }

                                    void sort_by_functor(vector<S> &v){
                                    sort(v.begin(), v.end(), Sgreater());
                                    }

                                    void sort_by_function(vector<S> &v){
                                    sort(v.begin(), v.end(), &Sgreater_func);
                                    }

                                    const int N = 10000000;
                                    vector<S> random_vector;

                                    ulint run(void foo(vector<S> &v)){
                                    vector<S> tmp(random_vector);
                                    foo(tmp);
                                    ulint checksum = 0;
                                    for(int i=0;i<tmp.size();++i){
                                    checksum += i *tmp[i].x ^ tmp[i].y;
                                    }
                                    return checksum;
                                    }

                                    void measure(void foo(vector<S> & v)){

                                    ulint check_sum = 0;

                                    // warm up
                                    const int WARMUP_ROUNDS = 3;
                                    const int TEST_ROUNDS = 10;

                                    for(int t=WARMUP_ROUNDS;t--;){
                                    COMPILER_BARRIER();
                                    check_sum += run(foo);
                                    COMPILER_BARRIER();
                                    }

                                    for(int t=TEST_ROUNDS;t--;){
                                    COMPILER_BARRIER();
                                    auto start = std::chrono::high_resolution_clock::now();
                                    COMPILER_BARRIER();
                                    check_sum += run(foo);
                                    COMPILER_BARRIER();
                                    auto end = std::chrono::high_resolution_clock::now();
                                    COMPILER_BARRIER();
                                    auto duration_ns = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();

                                    cout << "Took " << duration_ns << "s to complete round" << endl;
                                    }

                                    cout << "Checksum: " << check_sum << endl;
                                    }

                                    #define M(x)
                                    cout << "Measure " #x " on " << N << " items:" << endl;
                                    measure(x);

                                    int main(){
                                    random_vector.reserve(N);

                                    for(int i=0;i<N;++i){
                                    random_vector.push_back(S{rand(), rand()});
                                    }

                                    M(sort_by_operator);
                                    M(sort_by_lambda);
                                    M(sort_by_functor);
                                    M(sort_by_function);
                                    return 0;
                                    }


                                    What it does is it creates a random vector, and then measures how much time is required to copy it and sort the copy of it (and compute some checksum to avoid too vigorous dead code elimination).



                                    I was compiling with g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)



                                    $ g++ -O2 -o sort sort.cpp && ./sort


                                    Here are results:



                                    Measure sort_by_operator on 10000000 items:
                                    Took 0.994285s to complete round
                                    Took 0.990162s to complete round
                                    Took 0.992103s to complete round
                                    Took 0.989638s to complete round
                                    Took 0.98105s to complete round
                                    Took 0.991913s to complete round
                                    Took 0.992176s to complete round
                                    Took 0.981706s to complete round
                                    Took 0.99021s to complete round
                                    Took 0.988841s to complete round
                                    Checksum: 18446656212269526361
                                    Measure sort_by_lambda on 10000000 items:
                                    Took 0.974274s to complete round
                                    Took 0.97298s to complete round
                                    Took 0.964506s to complete round
                                    Took 0.96899s to complete round
                                    Took 0.965773s to complete round
                                    Took 0.96457s to complete round
                                    Took 0.974286s to complete round
                                    Took 0.975524s to complete round
                                    Took 0.966238s to complete round
                                    Took 0.964676s to complete round
                                    Checksum: 18446656212269526361
                                    Measure sort_by_functor on 10000000 items:
                                    Took 0.964359s to complete round
                                    Took 0.979619s to complete round
                                    Took 0.974027s to complete round
                                    Took 0.964671s to complete round
                                    Took 0.964764s to complete round
                                    Took 0.966491s to complete round
                                    Took 0.964706s to complete round
                                    Took 0.965115s to complete round
                                    Took 0.964352s to complete round
                                    Took 0.968954s to complete round
                                    Checksum: 18446656212269526361
                                    Measure sort_by_function on 10000000 items:
                                    Took 1.29942s to complete round
                                    Took 1.3029s to complete round
                                    Took 1.29931s to complete round
                                    Took 1.29946s to complete round
                                    Took 1.29837s to complete round
                                    Took 1.30132s to complete round
                                    Took 1.3023s to complete round
                                    Took 1.30997s to complete round
                                    Took 1.30819s to complete round
                                    Took 1.3003s to complete round
                                    Checksum: 18446656212269526361


                                    Looks like all the options except for passing function pointer are very similar, and passing a function pointer causes +30% penalty.



                                    It also looks like the operator< version is ~1% slower (I repeated the test multiple times and the effect persists), which is a bit strange as it suggests that the generated code is different (I lack skill to analyze --save-temps output).







                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Jun 9 '18 at 6:11









                                    Chris Reid

                                    30927




                                    30927










                                    answered Apr 26 '18 at 10:38









                                    qbolecqbolec

                                    3,23722431




                                    3,23722431























                                        1














                                            // sort algorithm example
                                        #include <iostream> // std::cout
                                        #include <algorithm> // std::sort
                                        #include <vector> // std::vector
                                        using namespace std;
                                        int main () {
                                        char myints = {'F','C','E','G','A','H','B','D'};
                                        vector<char> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
                                        // using default comparison (operator <):
                                        sort (myvector.begin(), myvector.end()); //(12 32 45 71)26 80 53 33
                                        // print out content:
                                        cout << "myvector contains:";
                                        for (int i=0; i!=8; i++)
                                        cout << ' ' <<myvector[i];
                                        cout << 'n';
                                        system("PAUSE");
                                        return 0;
                                        }





                                        share|improve this answer




























                                          1














                                              // sort algorithm example
                                          #include <iostream> // std::cout
                                          #include <algorithm> // std::sort
                                          #include <vector> // std::vector
                                          using namespace std;
                                          int main () {
                                          char myints = {'F','C','E','G','A','H','B','D'};
                                          vector<char> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
                                          // using default comparison (operator <):
                                          sort (myvector.begin(), myvector.end()); //(12 32 45 71)26 80 53 33
                                          // print out content:
                                          cout << "myvector contains:";
                                          for (int i=0; i!=8; i++)
                                          cout << ' ' <<myvector[i];
                                          cout << 'n';
                                          system("PAUSE");
                                          return 0;
                                          }





                                          share|improve this answer


























                                            1












                                            1








                                            1







                                                // sort algorithm example
                                            #include <iostream> // std::cout
                                            #include <algorithm> // std::sort
                                            #include <vector> // std::vector
                                            using namespace std;
                                            int main () {
                                            char myints = {'F','C','E','G','A','H','B','D'};
                                            vector<char> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
                                            // using default comparison (operator <):
                                            sort (myvector.begin(), myvector.end()); //(12 32 45 71)26 80 53 33
                                            // print out content:
                                            cout << "myvector contains:";
                                            for (int i=0; i!=8; i++)
                                            cout << ' ' <<myvector[i];
                                            cout << 'n';
                                            system("PAUSE");
                                            return 0;
                                            }





                                            share|improve this answer













                                                // sort algorithm example
                                            #include <iostream> // std::cout
                                            #include <algorithm> // std::sort
                                            #include <vector> // std::vector
                                            using namespace std;
                                            int main () {
                                            char myints = {'F','C','E','G','A','H','B','D'};
                                            vector<char> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
                                            // using default comparison (operator <):
                                            sort (myvector.begin(), myvector.end()); //(12 32 45 71)26 80 53 33
                                            // print out content:
                                            cout << "myvector contains:";
                                            for (int i=0; i!=8; i++)
                                            cout << ' ' <<myvector[i];
                                            cout << 'n';
                                            system("PAUSE");
                                            return 0;
                                            }






                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Dec 24 '13 at 16:21









                                            Amin AlomaisiAmin Alomaisi

                                            212




                                            212























                                                1














                                                You can use user defined comparator class.



                                                class comparator
                                                {
                                                int x;
                                                bool operator()( const comparator &m, const comparator &n )
                                                {
                                                return m.x<n.x;
                                                }
                                                }





                                                share|improve this answer




























                                                  1














                                                  You can use user defined comparator class.



                                                  class comparator
                                                  {
                                                  int x;
                                                  bool operator()( const comparator &m, const comparator &n )
                                                  {
                                                  return m.x<n.x;
                                                  }
                                                  }





                                                  share|improve this answer


























                                                    1












                                                    1








                                                    1







                                                    You can use user defined comparator class.



                                                    class comparator
                                                    {
                                                    int x;
                                                    bool operator()( const comparator &m, const comparator &n )
                                                    {
                                                    return m.x<n.x;
                                                    }
                                                    }





                                                    share|improve this answer













                                                    You can use user defined comparator class.



                                                    class comparator
                                                    {
                                                    int x;
                                                    bool operator()( const comparator &m, const comparator &n )
                                                    {
                                                    return m.x<n.x;
                                                    }
                                                    }






                                                    share|improve this answer












                                                    share|improve this answer



                                                    share|improve this answer










                                                    answered Aug 8 '17 at 11:47







                                                    user8385974






























                                                        0














                                                        To sort a vector you can use the sort() algorithm in .



                                                        sort(vec.begin(),vec.end(),less<int>());


                                                        The third parameter used can be greater or less or any function or object can also be used. However the default operator is < if you leave third parameter empty.



                                                        // using function as comp
                                                        std::sort (myvector.begin()+4, myvector.end(), myfunction);
                                                        bool myfunction (int i,int j) { return (i<j); }

                                                        // using object as comp
                                                        std::sort (myvector.begin(), myvector.end(), myobject);





                                                        share|improve this answer




























                                                          0














                                                          To sort a vector you can use the sort() algorithm in .



                                                          sort(vec.begin(),vec.end(),less<int>());


                                                          The third parameter used can be greater or less or any function or object can also be used. However the default operator is < if you leave third parameter empty.



                                                          // using function as comp
                                                          std::sort (myvector.begin()+4, myvector.end(), myfunction);
                                                          bool myfunction (int i,int j) { return (i<j); }

                                                          // using object as comp
                                                          std::sort (myvector.begin(), myvector.end(), myobject);





                                                          share|improve this answer


























                                                            0












                                                            0








                                                            0







                                                            To sort a vector you can use the sort() algorithm in .



                                                            sort(vec.begin(),vec.end(),less<int>());


                                                            The third parameter used can be greater or less or any function or object can also be used. However the default operator is < if you leave third parameter empty.



                                                            // using function as comp
                                                            std::sort (myvector.begin()+4, myvector.end(), myfunction);
                                                            bool myfunction (int i,int j) { return (i<j); }

                                                            // using object as comp
                                                            std::sort (myvector.begin(), myvector.end(), myobject);





                                                            share|improve this answer













                                                            To sort a vector you can use the sort() algorithm in .



                                                            sort(vec.begin(),vec.end(),less<int>());


                                                            The third parameter used can be greater or less or any function or object can also be used. However the default operator is < if you leave third parameter empty.



                                                            // using function as comp
                                                            std::sort (myvector.begin()+4, myvector.end(), myfunction);
                                                            bool myfunction (int i,int j) { return (i<j); }

                                                            // using object as comp
                                                            std::sort (myvector.begin(), myvector.end(), myobject);






                                                            share|improve this answer












                                                            share|improve this answer



                                                            share|improve this answer










                                                            answered Aug 2 '16 at 20:38









                                                            Prashant ShubhamPrashant Shubham

                                                            165114




                                                            165114























                                                                0














                                                                typedef struct Freqamp{
                                                                double freq;
                                                                double amp;
                                                                }FREQAMP;

                                                                bool struct_cmp_by_freq(FREQAMP a, FREQAMP b)
                                                                {
                                                                return a.freq < b.freq;
                                                                }

                                                                main()
                                                                {
                                                                vector <FREQAMP> temp;
                                                                FREQAMP freqAMP;

                                                                freqAMP.freq = 330;
                                                                freqAMP.amp = 117.56;
                                                                temp.push_back(freqAMP);

                                                                freqAMP.freq = 450;
                                                                freqAMP.amp = 99.56;
                                                                temp.push_back(freqAMP);

                                                                freqAMP.freq = 110;
                                                                freqAMP.amp = 106.56;
                                                                temp.push_back(freqAMP);

                                                                sort(temp.begin(),temp.end(), struct_cmp_by_freq);
                                                                }


                                                                if compare is false, it will do "swap".






                                                                share|improve this answer




























                                                                  0














                                                                  typedef struct Freqamp{
                                                                  double freq;
                                                                  double amp;
                                                                  }FREQAMP;

                                                                  bool struct_cmp_by_freq(FREQAMP a, FREQAMP b)
                                                                  {
                                                                  return a.freq < b.freq;
                                                                  }

                                                                  main()
                                                                  {
                                                                  vector <FREQAMP> temp;
                                                                  FREQAMP freqAMP;

                                                                  freqAMP.freq = 330;
                                                                  freqAMP.amp = 117.56;
                                                                  temp.push_back(freqAMP);

                                                                  freqAMP.freq = 450;
                                                                  freqAMP.amp = 99.56;
                                                                  temp.push_back(freqAMP);

                                                                  freqAMP.freq = 110;
                                                                  freqAMP.amp = 106.56;
                                                                  temp.push_back(freqAMP);

                                                                  sort(temp.begin(),temp.end(), struct_cmp_by_freq);
                                                                  }


                                                                  if compare is false, it will do "swap".






                                                                  share|improve this answer


























                                                                    0












                                                                    0








                                                                    0







                                                                    typedef struct Freqamp{
                                                                    double freq;
                                                                    double amp;
                                                                    }FREQAMP;

                                                                    bool struct_cmp_by_freq(FREQAMP a, FREQAMP b)
                                                                    {
                                                                    return a.freq < b.freq;
                                                                    }

                                                                    main()
                                                                    {
                                                                    vector <FREQAMP> temp;
                                                                    FREQAMP freqAMP;

                                                                    freqAMP.freq = 330;
                                                                    freqAMP.amp = 117.56;
                                                                    temp.push_back(freqAMP);

                                                                    freqAMP.freq = 450;
                                                                    freqAMP.amp = 99.56;
                                                                    temp.push_back(freqAMP);

                                                                    freqAMP.freq = 110;
                                                                    freqAMP.amp = 106.56;
                                                                    temp.push_back(freqAMP);

                                                                    sort(temp.begin(),temp.end(), struct_cmp_by_freq);
                                                                    }


                                                                    if compare is false, it will do "swap".






                                                                    share|improve this answer













                                                                    typedef struct Freqamp{
                                                                    double freq;
                                                                    double amp;
                                                                    }FREQAMP;

                                                                    bool struct_cmp_by_freq(FREQAMP a, FREQAMP b)
                                                                    {
                                                                    return a.freq < b.freq;
                                                                    }

                                                                    main()
                                                                    {
                                                                    vector <FREQAMP> temp;
                                                                    FREQAMP freqAMP;

                                                                    freqAMP.freq = 330;
                                                                    freqAMP.amp = 117.56;
                                                                    temp.push_back(freqAMP);

                                                                    freqAMP.freq = 450;
                                                                    freqAMP.amp = 99.56;
                                                                    temp.push_back(freqAMP);

                                                                    freqAMP.freq = 110;
                                                                    freqAMP.amp = 106.56;
                                                                    temp.push_back(freqAMP);

                                                                    sort(temp.begin(),temp.end(), struct_cmp_by_freq);
                                                                    }


                                                                    if compare is false, it will do "swap".







                                                                    share|improve this answer












                                                                    share|improve this answer



                                                                    share|improve this answer










                                                                    answered Sep 1 '17 at 3:05









                                                                    brucebruce

                                                                    39128




                                                                    39128






























                                                                        draft saved

                                                                        draft discarded




















































                                                                        Thanks for contributing an answer to Stack Overflow!


                                                                        • Please be sure to answer the question. Provide details and share your research!

                                                                        But avoid



                                                                        • Asking for help, clarification, or responding to other answers.

                                                                        • Making statements based on opinion; back them up with references or personal experience.


                                                                        To learn more, see our tips on writing great answers.




                                                                        draft saved


                                                                        draft discarded














                                                                        StackExchange.ready(
                                                                        function () {
                                                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1380463%2fsorting-a-vector-of-custom-objects%23new-answer', 'question_page');
                                                                        }
                                                                        );

                                                                        Post as a guest















                                                                        Required, but never shown





















































                                                                        Required, but never shown














                                                                        Required, but never shown












                                                                        Required, but never shown







                                                                        Required, but never shown

































                                                                        Required, but never shown














                                                                        Required, but never shown












                                                                        Required, but never shown







                                                                        Required, but never shown







                                                                        Popular posts from this blog

                                                                        Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                                                                        Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                                                                        A Topological Invariant for $pi_3(U(n))$