Subscribed unsubscribe Subscribe Subscribe

C関数レベルのクロージャを C++ で実現?

前にlibffi を使ってクロージャが作れることは確認したけど、やや力技過ぎ。
ちょっと調べてみるとid:mb2syncさんの日記 (スターありがとうございました) に c_function というのが紹介されていたので試してみた。

#include <iostream>
#include "c_function.hpp"

struct my_functor {
    my_functor(int _c): c(_c) {}

    int operator()(int a, int b) {
        return a + b + c;
    } 

    int c;
};

template<int T_>
struct uniqueness {};

// WTF!
#define GEN_GUID() \
    ::uniqueness<(sizeof(__FILE__) * __LINE__>

#define MAKE_C_FUNCTION(sig, f) \
    ::redshift::base::make_c_function<GEN_GUID(), sig>(f)

template<typename Tguid_, typename Tcfun_, typename Tfun_>
inline void my_make_c_function(Tcfun_& retval, Tfun_& f)
{
    retval = ::redshift::base::make_c_function<Tguid_, Tcfun_, Tfun_>(f);
}

#define MY_MAKE_C_FUNCTION(ret, f) \
    ::my_make_c_function<GEN_GUID()>(ret, f)

int main(int, char**)
{
    my_functor f1(1), f2(2);
    int(*foo)(int, int);
    int(*bar)(int, int);
    MY_MAKE_C_FUNCTION(foo, f1);
    MY_MAKE_C_FUNCTION(bar, f2);
    std::cout << foo(1, 2) << std::endl;
    std::cout << bar(1, 2) << std::endl;

    return 0;
}

インスタンスを区別するために毎回ユニークな型を渡してやらないといけないというところは __FILE__ と __LINE__ でむりくりしのいでみたw だめ?
もちろん同じ行に 2 つ以上 MY_MAKE_C_FUNCTION を書くことはできません。