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の形でも、コンパイラの最適化次第では手書きファンクタと同等のコードを生成できるはずですが、手元で試した感じでは無理っぽいです。