boost::functionの話

C++テンプレートテクニック 7-3


boost::functionの話が出てきました。

言ってしまえば関数ポインタや関数オブジェクトが渡せるオブジェクトなんですが、それを実現するための実装が凄く難しい。

とりあえず難易度が高いので関数ポインタだけ受け取るクラスをちょっと勉強がてら実装してみました。

#include <iostream>
using std::cout; using std::endl;

template<class Func,class T>
class function_ptr {
public:
    static T invoke(void (*func)()) {
        Func f = reinterpret_cast<Func>(func);
        return f();
    }
};

template<class T>
class function;

template<class T>
class function<T()> {
private:
public:
    T (*m_invoke)(void (*)());
    void (*m_func)();
    
    template<class Func>
    function& operator=(Func func) {
        m_invoke = &function_ptr<Func,T>::invoke;
        m_func = reinterpret_cast<void(*)()>(func);
        return *this;
    }
    
    T operator()() {
        return m_invoke(m_func);
    }
};


int func () {
    cout << "func" << endl;
    return 0;
}

int main () {
    function<int()> f;
    
    f = &func;
    
    f();
    
    return 0;
}
$ main
func

かなりややこしいですね。カンペキに理解するまでまだ時間がかかりそうです。

あと上記では引数が無い関数を受け取ることしかできないのですが、これって引数がひとつ増える毎に別のクラスを用意しなくちゃならないんでしょうかね・・・。

なかなかヘビーです。

追記

gccでエラーが出てたので色々修正した。どうも関数ポインタはvoid*だと受け取れない模様。この辺まだ良く分かってない。。。