読者です 読者をやめる 読者になる 読者になる

methaneのブログ

このブログに乗せているサンプルコードはすべてNYSLです。

自分のメンバ関数をtransform()とかに渡す

方法を探していたら、cppllのML過去ログから発見!
http://ml.tietew.jp/cppll/cppll/article/8913
・・・2003年、「思兼」って俺だなぁ。こんなコメントした覚えあるなぁ。
とりあえずサンプル.

#include <vector>
#include <algorithm>
#include <functional>

struct Hoge {
    using namespace std;
    size_t foo(size_t x) const { return t_[x]; }
    vector<size_t> bar() {
        vector<size_t> before;
        // beforeに何か入る.

        vector<size_t> after;
        transform(before.begin(), before.end(), back_inserter(after),
                  bind1st(mem_fun(&Hoge::foo), this));
        return after;
    }
private:
    size_t t_[N];
};

で、今回の罠は、fooをそのままmem_funに渡せなくて、&Hoge::fooって書かないといけないこと。
そんなしょうもない罠に引っかかるくらいだったら、最初っからtransform使わないで、

        for (size_t i = 0; i < before.size(); ++i) {
            after.push_back(foo(before[i]));
        }

と書けば良かった。を知っていても、使わないという選択肢はある。タイプ数は対して減らないし、読みやすさも後者の方が上だ。あえて前者を選ぶのは自己満足以外の何物でもない。
もちろん、今回はtransformだったから後者の方が簡単というだけで、これがもっと複雑なアルゴリズムだと手で実装するよりもきちんと関数オブジェクトを作った方がいいんだけどね。

でも、 bind1st(mem_fun(bar), this) しなくても bar を size_t (size_t) な関数オブジェクトとして値渡しにできる言語を使えば最初から何も問題ないわけで、やっぱりオブジェクト指向と関数型のハイブリッド言語がこれからの主流になるべきだと思う。
C++の関数型っぽさはGenericsによる模倣であって、言語レベルで関数型パラダイムに対応していないのが、C++関数型プログラミングをするときの障害になっている。