mem_var_less
構造体のメンバ変数でソート/二分探索することって意外と多い気がします。
ラムダやバインダを使うと長くて読みにくく、いつも手作業でファンクタを書いていました。
毎回書くのも面倒になってきたので、mem_funやlessに似せて汎用のファンクタを作りました。
<hamigaki/functional.hpp>
template<class S, class T> class mem_var_less_t : public std::binary_function<S,S,bool> { public: explicit mem_var_less_t(T S::* p) : ptr_(p) { } bool operator()(const S& x, const S& y) const { return x.*ptr_ < y.*ptr_; } private: T S::* ptr_; }; template<class S, class T> inline mem_var_less_t<S,T> mem_var_less(T S::* p) { return mem_var_less_t<S,T>(p); }
こんな感じで使います。
struct hoge { int n; std::string s; }; // nでソート void sort_by_num(std::vector<hoge>& v) { std::sort(v.begin(), v.end(), hamigaki::mem_var_less(&hoge::n)); } // sでソート void sort_by_str(std::vector<hoge>& v) { std::sort(v.begin(), v.end(), hamigaki::mem_var_less(&hoge::s)); }
多くの場合、mem_var_lessに渡すメンバポインタはコンパイル時に決定できるので、テンプレートの引数にすることも考えました。
しかし、そうすると「構造体の型」、「メンバの型」、「メンバポインタの値」の3つを指定する必要があり、使い勝手が悪くなります。
mem_var_lessの形でも、コンパイラの最適化次第では手書きファンクタと同等のコードを生成できるはずですが、手元で試した感じでは無理っぽいです。