汎用LessBy
小さなクラスを特定のメンバの値を基準にしてソートしたい場合。
しかも、Boost.MultiIndexを使うのは大げさだなーという時。
C++11ならラムダ式で書けるが、それでもめんどくさい。
例:
class X{ int a; double b; public: // ...コンストラクタとか... int GetA() const { return a; } double GetB() const { return b; } }; std::vector<X> v; // X::aでソート std::sort(v.begin(), v.end(), [](const X& lhs, const X& rhs){ lhs.GetA() < rhs.GetA(); }) // X::bでソート std::sort(v.begin(), v.end(), [](const X& lhs, const X& rhs){ lhs.GetB() < rhs.GetB(); })
なので、関数で変換後の値を比較する汎用的なLessByがあると便利。
#include <functional> template<class T, class F> std::function<bool(const T&, const T&)> LessBy(F f) { return [f](const T& lhs, const T& rhs)->bool{ auto f_ = std::bind(f, std::placeholders::_1); return f_(lhs) < f_(rhs); }; }
使い方
/////////////////////////// // メンバ関数を使った変換 /////////////////////////// // X::GetAでソート sort(v.begin(), v.end(), LessBy<X>(&X::GetA)); // X::GetBでソート sort(v.begin(), v.end(), LessBy<X>(&X::GetA)); /////////////////////////////// // unary関数を使った変換 ////////////////////////////// int Transform(const &X); // Transformで変換した値で元のオブジェクトをソート sort(v.begin(), v.end(), LessBy<X>(&Transform));
GreaterByとかも作ろうと思ったら、比較の所を差し替えられるような高階関数を作ってやった方が良いんだろうなぁ。
関数の引数の型も推論させられれば
さらに言うと、このLessBy使ってsortすると関数が何度も評価されちゃうので、非常に効率悪そう。sortByは別にちゃんと最適化したものを作るべきかも。