Erase-Remove Ideomを少しでも楽に使うために。(自分用メモ)


こんな感じでコンテナの値を削除できるようにしてみた。

#include <algorithm>
#include <vector>

struct Hoge
{
    int num_;

    explicit Hoge(int i) : num_(i) {}
    int getnum() { return num_; }
};

int main(int argc, char** argv)
{
    std::vector<Hoge> v;
    v.push_back(Hoge(1));
    v.push_back(Hoge(1));
    v.push_back(Hoge(2));
    v.push_back(Hoge(2));
    v.push_back(Hoge(3));
    v.push_back(Hoge(3));

    // vからHoge::getnum() == 1なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_functor(&Hoge::getnum, 1)), // mem_equal_to_functorはHogeのメンバー関数getnumを呼び
            v.end());                                               // 1と比較してbool値を返す関数。
    // vからHoge::num_ == 3なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_member(&Hoge::num_, 3)),    // mem_equal_to_memberはHogeのメンバーnum_と
            v.end());                                               // 3を比較してbool値を返す関数。

    // vの中身を全て表示
    for(std::vector<Hoge>::iterator first = v.begin(), last = v.end(); first != last; ++first)
    {
        std:: cout << first->num_ << std::endl;
    }

    return 0;
}

実行結果

2
2

以下mem_equal_to_functor関数とmem_equal_to_member関数の実装付ソース。

// ----------------------------------------------------------------------------------------
#include <functional>

// メンバー関数用
template<class T, class U>
class mem_equal_to_functor_t
    : public std::binary_function<T, U, bool>
{
    U (T::*f_)();
public:
    explicit mem_equal_to_functor_t(U (T::*f)()) : f_(f) {}

    bool operator()(T& arg1, const U& arg2) const
    {
        return (arg1.*f_)() == arg2;
    }
};

// メンバー変数用
template<class T, class U>
class mem_equal_to_member_t
    : public std::binary_function<T, U, bool>
{
    U T::*member_;
public:
    explicit mem_equal_to_member_t(U T::*member) : member_(member) {}

    bool operator()(T& arg1, const U& arg2) const
    {
        return arg1.*member_ == arg2;
    }
};

// メンバー関数用関数オブジェクトを返す
template<class T, class U>
std::binder2nd<mem_equal_to_functor_t<T,U> >mem_equal_to_functor(U (T::*f)(), const U& u)
{
    return std::bind2nd(mem_equal_to_functor_t<T, U>(f), u);
}

// メンバー変数用関数オブジェクトを返す
template<class T, class U>
std::binder2nd<mem_equal_to_member_t<T,U> > mem_equal_to_member(U T::*m, const U& u)
{
    return std::bind2nd(mem_equal_to_member_t<T, U>(m), u);
}
// ----------------------------------------------------------------------------------------
#include <algorithm>
#include <vector>

struct Hoge
{
    int num_;

    explicit Hoge(int i) : num_(i) {}
    int getnum() { return num_; }
};

int main(int argc, char** argv)
{
    std::vector<Hoge> v;
    v.push_back(Hoge(1));
    v.push_back(Hoge(1));
    v.push_back(Hoge(2));
    v.push_back(Hoge(2));
    v.push_back(Hoge(3));
    v.push_back(Hoge(3));

    // vからHoge::getnum() == 1なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_functor(&Hoge::getnum, 1)), // mem_equal_to_functorはHogeのメンバー関数getnumを呼び
            v.end());                                               // 1と比較してbool値を返す関数。
    // vからHoge::num_ == 3なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_member(&Hoge::num_, 3)),    // mem_equal_to_memberはHogeのメンバーnum_と
            v.end());                                               // 3を比較してbool値を返す関数。

    // vの中身を全て表示
    for(std::vector<Hoge>::iterator first = v.begin(), last = v.end(); first != last; ++first)
    {
        std:: cout << first->num_ << std::endl;
    }

    return 0;
}

実行結果

2
2

当然このままじゃまともには使えない。==にしか使えない時点でイケテナイ。
でもこれを発展させていけばboost::bind見たいなのが作れる。
もう少し発展させるとしたら引数にstd::less()等の関数オブジェクトを受け取れるようにして==以外も実行できるようにする。
ただ、ラムダ式さえ使えるようになれば以下のようにかけるのでこんなものは要らない。

    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           [](Hoge& h) { return h.num_ == 1}),
            v.end());



ちなみに自分のプロジェクトではErase-Remove Ideom使ったら可読性が無いからダメって言われました。orz