|
Boost Users : |
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2008-08-09 15:51:30
AMDG
Scott McMurray wrote:
> On Fri, Aug 8, 2008 at 14:13, Jesse Perla <jlp400_at_[hidden]> 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
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net