#include <boost/optional.hpp>
#include <boost/bind.hpp>
#include <boost/preprocessor/slot/counter.hpp>
#include <iostream>
#include <ostream>
using namespace std;

template<unsigned ID,typename Functor>
boost::optional<Functor> &get_local()
{
    static boost::optional<Functor> local;
    return local;
}

template<unsigned ID,typename Functor>
typename Functor::result_type wrapper()
{
    return get_local<ID,Functor>().get()();
}

template<typename ReturnType>
struct Func
{
    typedef ReturnType (*type)();
};

template<unsigned ID,typename Functor>
typename Func<typename Functor::result_type>::type get_wrapper(Functor f)
{
    (get_local<ID,Functor>()) = f;
    return wrapper<ID,Functor>;
}

// ----------------------------------------------------------------------

void test(void (*fptr)())
{
    fptr();
}

struct SomeStruct
{
    int data;
    void some_method()
    {
        cout << data << endl;
    }
    void another_method()
    {
        cout << -data << endl;
    }
};

int main()
{
    SomeStruct local[] = { {11}, {22}, {33} };

#include BOOST_PP_UPDATE_COUNTER()
    test(get_wrapper<BOOST_PP_COUNTER>(  boost::bind(&SomeStruct::some_method,local[0]) ));
#include BOOST_PP_UPDATE_COUNTER()
    test(get_wrapper<BOOST_PP_COUNTER>(  boost::bind(&SomeStruct::another_method,local[0]) ));

#include BOOST_PP_UPDATE_COUNTER()
    test(get_wrapper<BOOST_PP_COUNTER>(  boost::bind(&SomeStruct::some_method,local[1]) ));
#include BOOST_PP_UPDATE_COUNTER()
    test(get_wrapper<BOOST_PP_COUNTER>(  boost::bind(&SomeStruct::another_method,local[1]) ));

#include BOOST_PP_UPDATE_COUNTER()
    test(get_wrapper<BOOST_PP_COUNTER>(  boost::bind(&SomeStruct::some_method,local[2]) ));
#include BOOST_PP_UPDATE_COUNTER()
    test(get_wrapper<BOOST_PP_COUNTER>(  boost::bind(&SomeStruct::another_method,local[2]) ));

#include BOOST_PP_UPDATE_COUNTER()
    std::cout<<BOOST_PP_COUNTER<<std::endl;
#include BOOST_PP_UPDATE_COUNTER()
    std::cout<<BOOST_PP_COUNTER<<std::endl;
#include BOOST_PP_UPDATE_COUNTER()
    std::cout<<BOOST_PP_COUNTER<<std::endl;
}
