1

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.

Claudiu
  • 224,032
  • 165
  • 485
  • 680

2 Answers2

2

The problem is that you are trying to bind to a template function, which doesn't work. You can get around this by replacing foo_then_smile with a functor as described here.

But for what it's worth; if the compiler you're using supports C++11, you can typically use lambdas in place of bindings. I find their syntax to be cleaner and more readable, and they would let you do an end-run around the problem you're experiencing:

ioService.post([]() { foo_then_smile( []() { foo(1, 2, 3); } ); });

Community
  • 1
  • 1
dlf
  • 9,045
  • 4
  • 32
  • 58
  • Technically, this is not answering the question. It doesn't say how to pass a bind expression to a bind expression. – sehe Apr 25 '14 at 22:27
  • The problem isn't passing bind to bind; it's binding to a template. The link I included explains how to handle that. – dlf Apr 25 '14 at 22:28
  • The question, though, is about passing bind to bind. I agree that there were more issues, but that doesn't make the question magically change :) – sehe Apr 25 '14 at 22:29
  • The question, as I read it, was "why doesn't this compile." :) I tried to provide two different solutions to the underlying issue. – dlf Apr 25 '14 at 22:32
  • +1 from me. the link you posted has essentially the same solution as sehe, though sehe did provide a fully working example which is much appreciated! – Claudiu Apr 25 '14 at 22:33
1

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!
sehe
  • 374,641
  • 47
  • 450
  • 633