Reputation: 229321
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.
Upvotes: 1
Views: 134
Reputation: 392911
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!
Upvotes: 1
Reputation: 9383
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); } ); });
Upvotes: 2