-2

I would like to create a class, call it MyClass which has three data members- a, b and c. I then wish to put many MyClass objects in to a std::Vector<MyClass> and then sort the Vector according to the a data members.

Is there an elegant way of doing this using the STL? I didn't want to re-invent the wheel and I am sure this can't be a first. In Java I guess I would use a Comparator.

user997112
  • 29,025
  • 43
  • 182
  • 361
  • 2
    You just need to implement `operator<()` – Retired Ninja Sep 03 '13 at 20:00
  • @RetiredNinja myvector.Sort() isn't going to know anything about operator<() surely? – user997112 Sep 03 '13 at 20:02
  • 1
    There is no `myvector.Sort()` unless you're not using a `std::vector` – Retired Ninja Sep 03 '13 at 20:04
  • @user997112: It doesn't need to "know about it"; the way C++ works is that the operator will just simply be found. Remember, the standard library code is in user space, so it's bound by all the same rules as your own code. If a matching `operator<` exists in scope, it'll be used; doesn't matter that the person who wrote `std::vector` for your platform is unaware that you'd do that. – Lightness Races in Orbit Sep 03 '13 at 20:41
  • @user997112: _(continued)_ Consider how the person who writes `template void foo(T t) { bar(t); }` doesn't need to know anything about which overloads are available for `bar`. If there is one, it'll be used. If there are none, you will get an overload resolution failure error. If there are multiple, you will get an ambiguity error. The person who wrote the library does not care -- it is up to you to provide that implementation, and once you do everything works well. – Lightness Races in Orbit Sep 03 '13 at 20:43
  • @LightnessRacesinOrbit I meant- I didnt realise sort() just looks at the < operator.... – user997112 Sep 03 '13 at 20:51
  • @user997112: Okay. Well, [it does](http://en.cppreference.com/w/cpp/algorithm/sort). :) (_The documentation is your friend..._) – Lightness Races in Orbit Sep 03 '13 at 21:07

4 Answers4

5

There are 3 ways to do this using std::sort.

  • Implement an operator< function in the MyClass class.
  • Pass a function to sort that takes two const &MyClass reference parameters and returns bool true when the first object is less than the second.
  • Pass a functor object (a class that implements operator()) to sort; as with the stand-alone function, operator() should take two const &MyClass parameters and return a bool. Since the object can have internal state, you can use it to dynamically determine which field to sort on for example, or whether the sort should be ascending or descending.

First option:

bool MyClass::operator<(const MyClass &rhs)
{
    return a < rhs.a;
}

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

Second option:

bool CompareMyClass(const MyClass &lhs, const MyClass &rhs)
{
    return lhs.a < rhs.a; // this function will need to be declared friend if a is private
}

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

Third option:

struct MyFunctor
{
    bool operator()(const MyClass &lhs, const MyClass &rhs) const
    {
        return lhs.a < rhs.a;
    }
};

std::sort(vec.begin(), vec.end(), MyFunctor());
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
3

The following should do the trick:

bool operator < (MyClass const& lhs, MyClass const& rhs)
{
    return lhs.a < rhs.a;
}

std::sort requires the value_type of the iterators to be less-than comparable, or in more technical terms, they must form a strict weak ordering. Given the code above, you should now be able to sort it like any other type:

std::sort(std::begin(my_classes), std::end(my_classes));

assuming my_classes is a std::vector.

bstamour
  • 7,746
  • 1
  • 26
  • 39
1

To create a comparator in the Java sense (i.e. an external comparison function which is not part of the class definition), create a functor:

struct {
    bool operator()(const MyClass& c1, const MyClass& c2) {
        return c1.a < c2.a;
    }
} my_comparator;

and pass it into std::sort:

std::sort(std::begin(my_classes), std::end(my_classes), my_comparator);

Alternatively, if on C++11, use a lambda:

std::sort(my_classes.begin(), my_classes.end(), [](const MyClass& c1, const MyClass& c2) {
    return c1.a < c2.a;
});
nneonneo
  • 171,345
  • 36
  • 312
  • 383
0

You can code a compare function and use STL set To code a comparison implement like this :

bool operator<(MyClass other) const
{
    return (expression);
}
dzada
  • 5,344
  • 5
  • 29
  • 37