BekzhanKassenov's blog

By BekzhanKassenov, history, 9 years ago, translation, In English

Hello community, Happy New Year!

I came up with interesting macro which allows sort objects by some field. The code is laconic but requires C++11. Macro itself:

#define by(T, x) [](const T& a, const T& b) { return a.x < b.x; }

Usage:

struct Item {
    int a, b;
};

sort(arr, arr + N, by(Item, a));

Full example: http://pastebin.com/Cp5ZkwE4.

Happy New Year!

UPD: It was pointed out (in Russian discussion) that C++14 allows shorter version:

#define by(x) [](const auto& a, const auto& b) { return a.x < b.x; }
sort(arr, arr + N, by(a));
  • Vote: I like it
  • +122
  • Vote: I do not like it

| Write comment?
»
9 years ago, # |
  Vote: I like it +24 Vote: I do not like it

It is very useful! Thank you :)

»
9 years ago, # |
  Vote: I like it +5 Vote: I do not like it

Auto comment: topic has been updated by BekzhanKassenov (previous revision, new revision, compare).

»
9 years ago, # |
  Vote: I like it +1 Vote: I do not like it

Just for the fun, it is possible to do the same in c++03 without using any macro. It is not as short macro version, but at least you can't break it by passing something like x || 3 to it.

template<class T, class R, R T::* x> struct by {
    bool operator()(const T& a, const T& b) { return a.*x < b.*x; }
};

sort(arr, arr + N, by<Item, int, &Item::a>());
»
9 years ago, # |
  Vote: I like it +27 Vote: I do not like it

One can go even further and do smth like this:

#define by(T, ...) [](const decltype(T)& a, const decltype(T)& b) { return a.__VA_ARGS__ < b.__VA_ARGS__; }

(decltype is to avoid manual typing of the type name)

Then one can write:

vector<pair<pair<SuperCoolStruct, int>, AnotherCoolStruct>> arr;
sort(arr.begin(), arr.end(), by(arr[0], first.first.someImportantField));