
AMDG Scott McMurray wrote:
On Fri, Aug 8, 2008 at 14:13, Jesse Perla <jlp400@nyu.edu> wrote:
Is there any way to get a normal function pointer out of a boost::function (with its state and potential bindings)? I want to have the option of calling existing optimization routines that are not functor aware.
If all you can pass is a, say, double(*)(double), then you might be somewhat out of luck when it comes to nice solutions. You can always use global variables to pass the state, but those are obviously not nice.)
Here's a quick hack that hides the global variables: #include <map> #include <vector> #include <boost/function.hpp> #include <boost/mpl/for_each.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/pair.hpp> #include <boost/preprocessor/iteration/local.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_binary_params.hpp> #include <boost/preprocessor/repetition/enum_trailing_params.hpp> template<class Sig, class Id> struct function_holder; #define BOOST_PP_LOCAL_MACRO(n) \ \ template<class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class T), class Id> \ struct function_holder<R(BOOST_PP_ENUM_PARAMS(n, T)), Id> { \ static boost::function<R(BOOST_PP_ENUM_PARAMS(n, T))> impl; \ static R function(BOOST_PP_ENUM_BINARY_PARAMS(n, T, t)) { \ return(impl(BOOST_PP_ENUM_PARAMS(n, t))); \ } \ }; \ \ template<class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class T), class Id> \ boost::function<R(BOOST_PP_ENUM_PARAMS(n, T))> \ function_holder<R(BOOST_PP_ENUM_PARAMS(n, T)), Id>::impl; #define BOOST_PP_LOCAL_LIMITS (0, 10) #include BOOST_PP_LOCAL_ITERATE() template<class Sig, class Id, int Size> struct function_pool { static std::map<Sig*, boost::function<Sig>*> allocated_functions; static std::vector<std::pair<Sig*, boost::function<Sig>*> > free_functions; struct insert_free_function { template<class N> void operator()(const N&) const { free_functions.push_back(std::make_pair( &function_holder<Sig, boost::mpl::pair<Id, N> >::function, &function_holder<Sig, boost::mpl::pair<Id, N> >::impl)); } }; static void init() { boost::mpl::for_each<boost::mpl::range_c<int, 0, Size>
(insert_free_function()); } static Sig* allocate(const boost::function<Sig>& f) { std::pair<Sig*, boost::function<Sig>*> result = free_functions.back(); *result.second = f; allocated_functions.insert(result); free_functions.pop_back(); return(result.first); } static void free(Sig* victim) { typename std::map<Sig*, boost::function<Sig>*>::iterator pos = allocated_functions.find(victim); free_functions.push_back(*pos); allocated_functions.erase(pos); } };
template<class Sig, class Id, int Size> std::map<Sig*, boost::function<Sig>*> function_pool<Sig, Id, Size>::allocated_functions; template<class Sig, class Id, int Size> std::vector<std::pair<Sig*, boost::function<Sig>*> > function_pool<Sig, Id, Size>::free_functions; #include <iostream> struct pool : function_pool<void(int), pool, 10> {}; struct hello { void operator()(int) const { std::cout << "Hello, "; } }; struct world { void operator()(int) const { std::cout << "World!" << std::endl; } }; int main() { pool::init(); void (*hello_function)(int) = pool::allocate(hello()); void (*world_function)(int) = pool::allocate(world()); hello_function(1); world_function(1); pool::free(hello_function); pool::free(world_function); } In Christ, Steven Watanabe