A few boost::function questions

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. And hopefully including Fortran and C functions as well? I imagine that any solution to this would be hacky and potentially slow, but it would be nice to have the option without porting every optimization routine. Also, what is the general consensus on http://www.codeproject.com/KB/cpp/FastDelegate.aspx these days? How much faster is the overhead? From what I read in this link, it is virtually none vs. 20nanoseconds'ish for boost::function. Are there any caveats or reasons not to apply this widely (assuming that I am using only the Intel compiler)? And am I able to hack out a function pointer out of this library? Does using a binding library remove the speed of the fast delegation? Last, I am having a little trouble understanding the "forwarding problem" as a library user. My main use-case is for dynamic programming. I will have a function of 3-4 parameters (an euler equation or bellman iteration). I will bind all but one of the parameters and then run an optimizer over the other one. However, what values are bound will be in a foreach. (i.e. choose a state space, foreach in statespace run optimizer to see policy function choice for each point in the statespace. iterate...) . Is this going to work with these libraries? Is boost::function combined with boost::binding the most semantically correct way to do this? Am I going to run into enormous overhead or the forwarding problem when I do this? Do nested bindings add in linear overhead? Thanks, Jesse

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. And hopefully including Fortran and C functions as well? I imagine that any solution to this would be hacky and potentially slow, but it would be nice to have the option without porting every optimization routine.
Boost.Thread needs to pass a plain function pointer to the native libraries, but has a boost::function<void()>. You can probably use the same trick it uses. (Though IIRC, it only works if you can pass a void* data argument that goes along with the function. 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.)

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
participants (3)
-
Jesse Perla
-
Scott McMurray
-
Steven Watanabe