Search code examples
c++functionboostfunctional-programmingboost-bind

Functional programming with boost: pass a boost::bind to a boost::bind


I'm attempting to take a functional approach to some code I am writing. In particular, I want to pass a function to another function which does something with it, and to then schedule that latter function on a boost::asio::io_service.

I tried the following (inspired by io_service.hpp's definition of io_service::post) as template <typename CompletionHandler> void post(CompletionHandler handler);):

#include <stdio.h>

#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>

template <typename FUNC>
void foo_then_smile(FUNC handler) {
    handler();
    printf("Smile!\n");
}

void foo(int a, int b, int c) {
    printf("The important answer is %d\n", a + b + c);
}

int main() {
    boost::asio::io_service ioService;

    ioService.post(boost::bind(foo_then_smile, boost::bind(foo, 1, 2, 3)));

    return 0;
}

But I get:

no matching function for call to 'bind(<unresolved overloaded function type>, boost::_bi::bind_t<void, void (*)(int, int, int), boost::_bi::list3<boost::_bi::value<int>, boost::_bi::value<int>, boost::_bi::value<int> > >)'

Followed by a huge list of candidates.


Solution

  • And if you can't use c++11, you can turn the function template into a polymorphic function object:

    struct foo_then_smile
    {
        typedef void result_type;
    
        template <typename FUNC>
            void operator()(FUNC handler) const {
                handler();
                printf("Smile!\n");
            }
    };
    

    And use it (note the protect to avoid mixing up the bind unwrappings):

    ioService.post(boost::bind(foo_then_smile(), 
                   boost::protect(boost::bind(foo, 1, 2, 3))));
    

    See it Live On Coliru

    #include <stdio.h>
    
    #include <boost/asio/io_service.hpp>
    #include <boost/bind.hpp>
    #include <boost/bind/protect.hpp>
    
    struct foo_then_smile
    {
        typedef void result_type;
    
        template <typename FUNC>
            void operator()(FUNC handler) const {
                handler();
                printf("Smile!\n");
            }
    };
    
    void foo(int a, int b, int c) {
        printf("The important answer is %d\n", a + b + c);
    }
    
    int main() {
        boost::asio::io_service ioService;
    
        ioService.post(boost::bind(foo_then_smile(), boost::protect(boost::bind(foo, 1, 2, 3))));
    
        ioService.run();
    }
    

    Prints:

    The important answer is 6
    Smile!