Suppose I have a function called subscribe() that takes a callback handler, which will be called when the event is triggered.
Now, I have another version, called subscribe2(). Everything is the same except that, when triggered, it needs to post it to an event queue. It is implemented using the original subscribe(), with a helper funciton called helper(). All it does is to bind the original handler and whatever additional arguments into a functor, and call postToEventQueue().
Now, I wonder if there's a way to eliminate the helper function, so that in subsribe2(), I can somehow package the postToTaskQueue() function and the original callback handler directly, and pass it to subscribe(). The reason is that I have a lot of different handler types, and it is tedious and tiring to introduce helper function all over the place. Afterall, boost::bind is supposed to return a new function given the original function, right? I am trying to generate the helper function directly with boost::bind.
One attempt is to say
subscribe(boost::bind(boost::bind(postToTaskQueue, boost::bind(_1, _2)), cb, _1));
in subscribe2(), but it doesn't work. Is it possible at all?
Please see detailed example code below. Thanks!
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
typedef boost::function<void(int)> SomeCallback;
typedef boost::function<void()> Task;
void handler(int i){
std::cout << "i=" << i <<std::endl;
}
void subscribe(SomeCallback cb)
{
cb(100); //just invoke the callback for simplicity
}
void postToTaskQueue(Task t)
{
t(); // just invoke the task for simplicity
}
void helper(SomeCallback cb, int i)
{
Task t = boost::bind(cb, i);
postToTaskQueue(t);
}
void subscribe2(SomeCallback cb)
{
subscribe(boost::bind(helper, cb, _1));
// this does not work..
// subscribe(boost::bind(boost::bind(postToTaskQueue, boost::bind(_1, _2)), cb, _1));
}
int main()
{
subscribe(boost::bind(handler, _1));
subscribe2(boost::bind(handler, _1));
}
I have no answer. However, I've played with this for over an hour:
boost::bind
boost::apply<>
boost::protect
Maybe, just maybe, a more experienced boost developer could take it from here:
void subscribe2(SomeCallback cb)
{
using boost::bind;
using boost::protect;
using boost::apply;
bind(cb, 41)(); // OK of course
postToTaskQueue(bind(cb, 46)); // also fine
bind(postToTaskQueue, protect(bind(cb, 146)))(); // boost::protect to the rescue
postToTaskQueue(bind(apply<void>(), cb, 47));
bind(postToTaskQueue, protect(bind(apply<void>(), cb, 147)))();
The above prints
i=41
i=46
i=146
i=47
i=147
But, sadly, I can't seem to make this this thing parameterizing (as suggested should work in the documentation on composition using Nested Binds):
// but sadly, this appears to not work ...
auto hmm = bind(postToTaskQueue, bind(apply<void>(), cb, _1));
hmm(997); // FAIL
}
Here's a fully compiled demo showing the state of affairs: Live on Coliru
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <boost/bind/apply.hpp>
#include <iostream>
typedef boost::function<void(int)> SomeCallback;
typedef boost::function<void()> Task;
void handler(int i){
std::cout << "i=" << i <<std::endl;
}
void subscribe(SomeCallback cb)
{
cb(100); //just invoke the callback for simplicity
}
void postToTaskQueue(Task t)
{
t(); // just invoke the task for simplicity
}
void helper(SomeCallback cb, int i)
{
postToTaskQueue(boost::bind(cb, i));
}
void subscribe2(SomeCallback cb)
{
using boost::bind;
using boost::protect;
using boost::apply;
bind(cb, 41)(); // OK of course
postToTaskQueue(bind(cb, 46)); // also find
bind(postToTaskQueue, protect(bind(cb, 146)))(); // boost::protect to the rescue
postToTaskQueue(bind(apply<void>(), cb, 47));
bind(postToTaskQueue, protect(bind(apply<void>(), cb, 147)))();
// but sadly, this appears to not work ...
auto hmm = bind(postToTaskQueue, bind(apply<void>(), cb, _1));
//hmm(997); // FAIL
}
int main()
{
subscribe (boost::bind(handler, _1));
subscribe2(boost::bind(handler, _1));
}
You are binding a function (helper) that itself does a bind. That mean you are (indirectly) binding bind itself. This is the key insight. The solution is to write a little bind function object wrapper that can itself be bound. Here's what my solution looks like:
#include <utility>
#include <iostream>
#include <boost/function.hpp>
#include <boost/phoenix/bind.hpp>
#include <boost/phoenix/core/argument.hpp>
using boost::phoenix::placeholders::_1;
typedef boost::function<void(int)> SomeCallback;
typedef boost::function<void()> Task;
struct bind_t
{
template<typename Sig>
struct result;
template<typename This, typename ...A>
struct result<This(A...)>
{
typedef decltype(boost::phoenix::bind(std::declval<A>()...)) type;
};
template<typename ...A>
auto operator()(A &&...a) const -> decltype(boost::phoenix::bind(std::forward<A>(a)...))
{
return boost::phoenix::bind(std::forward<A>(a)...);
}
};
bind_t const bind = {};
void handler(int i)
{
std::cout << "i=" << i <<std::endl;
}
void subscribe(SomeCallback cb)
{
cb(100); //just invoke the callback for simplicity
}
void postToTaskQueue(Task t)
{
t(); // just invoke the task for simplicity
}
void subscribe2(SomeCallback cb)
{
subscribe(bind(postToTaskQueue, bind(bind, cb, _1)));
}
int main()
{
subscribe(::bind(handler, _1));
subscribe2(::bind(handler, _1));
}
I switched to Phoenix's bind because it lets you bind polymorphic function objects (which bind above is).
This solution requires decltype. It also uses variadics, but that can be faked with overloads up to N arguments. Rvalue refs are also a convenience that can be done without with a little more work.
Related
I am trying to use std::bind to bind to a function and store it into my std::function callback object. The code I wrote is the simplified version of my actual code. The below code does not compile, says
_1 was not declared in the scope
Note: I know the same can be done using a lambda. However the function handler is already present and need to be used else I need to call the handler inside the lambda.
#include <iostream>
#include <functional>
typedef std:: function<void(int)> Callback;
template <class T>
class Add
{
public:
Add(Callback c)
{
callback = c;
}
void add(T a, T b)
{
callback(a+b);
}
private:
Callback callback;
};
void handler(int res)
{
printf("result = %d\n", res);
}
int main(void)
{
// create a callback
// I know it can be done using lambda
// but I want to use bind to handler here
Callback c = std::bind(handler, _1);
/*Callback c = [](int res)
{
printf("res = %d\n", res);
};*/
// create template object with
// the callback object
Add<int> a(c);
a.add(10,20);
}
The placeholders _1, _2, _3... are placed in namespace std::placeholders, you should qualify it like
Callback c = std::bind(handler, std::placeholders::_1);
Or
using namespace std::placeholders;
Callback c = std::bind(handler, _1);
Placeholders are in own namespace in the std namespace.
Add using namespace std::placeholders or use std::placeholders::_1
Good examples: std::placeholders::_1, std::placeholders::_2, ..., std::placeholders::_N
I want to have a class that can have a callback set to a pointer to member function. This means I need to store the address of the function, and the address of the object instance. The function should have the proper prototype and return value to what the callback expects.
I've played around with std::mem_fn and boost::bind (with the Boost Signals2 library), but it seems like I have to know the type of the class containing the callback function to store this information.
It seems like there should be a way to store a couple void* that would point to any object/function, but this obviously smells funny, loses type safety, etc.
Given a class SomeClass with a method some_method, I want to be able to do something like this:
SomeClass obj;
some_other_class.set_callback(&SomeClass::some_method, &obj);
Here is how I was able to accomplish this using Boost. Note that this uses Boost signals, and seems like overkill for a simple callback. Also, there is the issue of signals using "combiners" to determine the return value of the callback, since there are potentially multiple slots connected to a single signal. I only need support for a single callback. Also note that this is a complete compilable program:
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <string>
using namespace std;
struct MessageSource
{
boost::signals2::signal<void(const string &)> send_message;
typedef boost::signals2::signal<void(const string &)>::slot_type slot_type;
template<typename A, typename B>
boost::signals2::connection connect(A a, B b)
{
return send_message.connect(boost::bind(a, b, _1));
}
void send_msg(const string& msg)
{
send_message(msg);
}
};
struct Printer
{
void print(const string& msg) { std::cout << msg << std::endl; };
};
int main()
{
{
Printer p;
MessageSource s;
s.connect(&Printer::print, &p);
s.send_msg("test");
}
system("pause");
return 0;
}
I think the magic here is the fact that boost::bind() is able to handle a variety of types for its first argument. I just don't get how it can hold onto it in a private field of some sort without knowing the type...
Is this a case where a functor is really the right solution? It seems like member functions are so much more convenient to use...
Based on the comment by cdhowie above, I was able to come up with the following solution using std::function and std::bind:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
struct MessageSource
{
function<void(const string& msg)> _callback;
template<typename A, typename B>
void connect(A func_ptr, B obj_ptr)
{
_callback = bind(func_ptr, obj_ptr, placeholders::_1);
}
void send_msg(const string& msg)
{
if (_callback)
_callback(msg);
}
void disconnect()
{
_callback = nullptr;
}
};
struct Printer
{
void print(const string& msg) { std::cout << msg << std::endl; };
};
int main()
{
{
Printer p;
MessageSource s;
s.connect(&Printer::print, &p);
s.send_msg("test");
s.disconnect();
s.send_msg("test again");
}
system("pause");
return 0;
}
How to specify lambda, std::bind result or any other std::function as argument for unix signal function?
I'm trying the following
std::function<void(int)> handler1 = std::bind(&cancellation_token::cancel, &c);
std::function<void(int)> handler2 = [&c](int) { c.cancel(); };
but it doesn't work, because both
handler1.target<void(int)>()
and
handler2.target<void(int)>()
return null
It works if I initialize handler with free function pointer
void foo(int) { ... }
std::function<void(int)> handler = foo;
but this is absolutely useless. I need to capture some local variables, so I need either bind or lambda.
Actually I understand why it doesn't work. Documentation says that target function returns a pointer to the stored function if target_type() == typeid(T), otherwise a null pointer. I don't understand how to make it work.
Any suggestions?
Since it's constructed by bind, or lambda with captured-data, you cannot convert it to free function, since target function works by typeid, std::function saves it in runtime, not for type T, with which function is templated. For std::bind it will be some library-type and for lambda it will be some unnamed type.
You can use a dispatcher-like approach associating signal numbers to std::functions through a map.
You just need a map to hold the std::functions accesible from a free function:
std::unordered_map<int, std::function<void(int)>> signalHandlers;
And a generic handler (free function) to map the signal number to the function:
void dispatcher(int signal) {
// this will call a previously saved function
signalHandlers.at(signal)(signal);
}
Implementation example
main.cpp
#include <iostream>
#include <thread>
#include <csignal>
#include "cppsignal.hpp"
int main() {
bool stop = false;
// set a handler as easy as this
CppSignal::setHandler(SIGINT, [&stop] (int) { stop = true; });
while (!stop) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Bye" << std::endl;
return 0;
}
cppsignal.cpp
#include <cstring> // strsignal
#include <csignal>
#include <string>
#include <stdexcept>
#include <unordered_map>
#include <mutex>
#include "signal.hpp"
namespace CppSignal {
std::timed_mutex signalHandlersMutex;
std::unordered_map<int, std::function<void(int)>> signalHandlers;
// generic handler (free function) to set as a handler for any signal
void dispatcher(int signal) {
std::unique_lock<std::timed_mutex> lock(signalHandlersMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::seconds(1))) {
// unable to get the lock. should be a strange case
return;
}
auto it = signalHandlers.find(signal);
if (it != signalHandlers.end()) {
it->second(signal);
}
}
void registerHandler(int signal, const std::function<void(int)>& handler) {
std::lock_guard<std::timed_mutex> lock(signalHandlersMutex);
signalHandlers.emplace(signal, handler);
}
// this is the only method you will use
void setHandler(int signal, const std::function<void(int)>& handler, int flags) {
// configure sigaction structure
struct sigaction action;
if (sigfillset(&action.sa_mask) == -1) {
throw std::runtime_error("sigfillset failed");
}
action.sa_flags = flags;
action.sa_handler = dispatcher;
// set handler for the signal
if (sigaction(signal, &action, nullptr) == -1 && signal < __SIGRTMIN) {
throw std::runtime_error("Fail at configuring handler for signal: " + std::string(strsignal(signal)));
}
registerHandler(signal, handler);
}
}
cppsignal.hpp
#ifndef __CPPSIGNAL_HPP
#define __CPPSIGNAL_HPP
#include <functional>
namespace CppSignal {
void setHandler(int signal, const std::function<void(int)>& handler, int flags=0);
}
#endif
sighandler_t is defined to be a pointer to a function with the following definition:
void func(int);
Since std::bind and lambdas return functors, it is not possible to directly use them as signal handler. As a workaround you can use your own wrapper functions like
class SignalHandlerBase
{
public:
virtual void operator(int) = 0;
};
template <class T>
class SignalHandler : public SignalHandlerBase
{
T t;
public:
SignalHandler(T _t) : t(_t) { }
void operator(int i)
{
t(i);
}
};
class SignalManager
{
int sig;
SignalHandlerBase *shb;
static void handlerFunction(int i)
{
shb(i);
}
public:
SignalManager(int signal) : sig(signal), shb(nullptr) { signal(signal, &handlerFunction); }
template <class T>
void installHandler(T t)
{
delete shb;
shb = new SignalHandler<T>(t);
}
};
Use global instances of SignalManager to manage individual signals
C++11 1.9 [intro.execution]/6:
When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects which
are neither
of type volatile std::sig_atomic_t nor
lock-free atomic objects (29.4)
are unspecified during the execution of the signal handler, and the value of any
object not in either of these
two categories that is modified by the handler becomes undefined.
The only action you can realistically take portably in a signal handler is to change the value of a flag whose type is volatile std::sig_atomic_t or a lock-free std::atomic (Note that not all std::atomic objects are lock-free). Non-signal handling code can then poll that flag to respond to the occurrence of the signal.
N3787 has some interesting discussion about how to fix C++11 basically breaking signal handlers as a concept.
I'm trying to wrap std::packaged_task inside another class in order to be used together with a task scheduler.
At the moment I got it all working except std::future support. To get std::future support I figured out I need to use std::packaged_task for the get_future() function that it provides.
I've been trying whole day all sorts of ways to get this to work, but I seem to be unable to properly declare and initialise the packaged_task using the return value from a std::bind. I have tried to decipher the implementations of all the related libstdc++ functions such as std::async, std::future, std::thread etc but with no luck.
The following code is the implementation of both the not working version and the working one. To get it to work uncomment the two /* --- WORKS*/ and comment the other related line.
#include <vector>
#include <deque>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <iostream>
#include <chrono>
#include <functional>
#include <windows.h>
class task
{
private:
struct task_implementation_base
{
virtual void execute() = 0;
};
template <class callable>
struct task_implementation : public task_implementation_base
{
task_implementation(callable&& f) : /*m_task(std::forward<callable>(f)) WORKS*/m_task(f) { }
void execute() { m_task(); }
//callable m_task; // WORKS
std::packaged_task<typename result_of<callable>::type> m_task;
};
template <class callable>
std::shared_ptr<task_implementation<callable>> make_routine(callable&& f)
{
return std::make_shared<task_implementation<callable>>(std::forward<callable>(f));
}
public:
template <class callable, class... arguments>
task(callable&& f, arguments&&... args) : m_function(make_routine(std::bind(std::forward<callable>(f), std::forward<arguments>(args)...))) {}
void operator()() { run(); }
void run() { m_function->execute(); }
private:
std::shared_ptr<task_implementation_base> m_function;
};
int testint(int i)
{
std::cout << "test6" << " :: ran from thread " << std::this_thread::get_id() << "\n";
fflush(stdout);
return i+100;
}
void test(const char* text)
{
std::cout << text << " :: ran from thread " << std::this_thread::get_id() << "\n";
fflush(stdout);
}
class testclass
{
public:
void print1() { test("test3"); }
void print2() { test("test4"); }
void print3(const char* text) { test(text); }
};
int main()
{
testclass testclass1;
testclass* testclass2 = new testclass;
task test1(test, "test1");
task test2([]() { test("test2"); });
task test3(&testclass::print1, &testclass1);
task test4(&testclass::print2, &*testclass2);
task test5(&testclass::print3, &*testclass2, "test5");
task test6(&testint, 1);
test1();
test2();
test3();
test4();
test5();
test6();
Sleep(2000);
return 0;
}
I'm thinking the problem is typename result_of<callable>::type. I'm guessing it doesn't properly evaluates to the return type of the callable function.
I'm using c++ (Built by MinGW-builds project) 4.8.0 20121225 (experimental) on a Windows 8 64bit. I'm suspecting the errors are irrelevant since I guess I'm just simply trying to get this work the wrong way but here is a pastebin for the errors anyway: errors
std::packaged_task not only takes the result type of the invoked function as a template argument but also the types of the arguments you are passing to the to be invoked function.
You can define them as follows:
// somewhere
int foo(bool, int);
// somewhere else
std::packaged_task<int(bool, int)> p(foo);
To fix your code you need to add two empty parenthesis pairs. What I explained above also applies to std::result_of.
std::packaged_task<typename std::result_of<callable()>::type()> m_task;
It is only response to main topic question. "How to implement"
Example short implementation:
template <typename Signature> /// <---- 1
class Task;
template <typename Res, typename... ArgTypes>
class Task<Res(ArgTypes...)> /// <---- 2
{
public:
template <typename Function>
explicit Task(Function&& callback)
: _task{std::forward<Function>(callback)}
{ }
void execute(ArgTypes... args) noexcept(false)
{
//...
_task(std::forward<ArgTypes>(args)...);
}
private:
std::packaged_task<Res(ArgTypes...)> _task;
};
Not sure why step 1 & 2 are required but I did the same as in lib implementation. Maybe someone could extend this response.
typedef boost::function<void (int,bool)> MyCallback;
void RegisterCallback(MyCallback callback);
class A {
public:
void GoodCallback(int intArg,bool boolArg) {
printf("calling GoodCallback (%d,%s)\n",intArg,boolArg?"true":"false");
}
void BadCallback(int intArg) {
printf("calling BadCallback (%d)\n",intArg);
}
};
int TestFunction() {
A * myA=new A();
RegisterCallback(boost::bind(&A::GoodCallback,myA,_1,_2));
RegisterCallback(boost::bind(&A::BadCallback,myA,_1));
return 0;
}
Is there any way that I can make the second call to RegisterCallback not compile?
For context:
I recently changed the callback signature and added the bool argument. I thought I had updated everything that was using this, but I was mistaken. Other than renaming RegisterCallback everytime I change the signature, I would like to have a way to have the compiler enforce that all arguments are used.
The documentation says
Any extra arguments are silently ignored
It has to be this way in order to support _N placeholders. Witness:
void foo (int a, const char* b) {
std::cout << "called foo(" << a << "," << b << ")" << std::endl;
}
int main () {
boost::bind(foo,_1, _2)(1, "abc", foo, main, 2.0);
boost::bind(foo,_2, _5)(3.0, 2, foo, main, "def");
}
prints
called foo(1,abc)
called foo(2,def)
Any combination of arguments in the beginning, in the end or in the middle of the argument list can be ignored.
You need a simpler binder that doesn't support anything like _N placeholders. Boost doesn't seem to have one.
The problem isn't boost::function; the problem is that the function object boost::bind returns will take anything as parameters. Bind is, more or less, runtime defined, not compile-time defined. Therefore, the boost::bind object can be used with any boost::function.
[edit] OK, apparently boost::function is also a problem. But it's not the only problem.
You could always use std::function<...> instead.
The following does not compile on VS2010 SP1:
#include <functional>
void foo();
void bar(int);
int main()
{
std::function<void ()> f= std::bind(foo);
std::function<void ()> g= std::bind(bar); // does not match signature, does not compile.
return 0;
}
I'm a bit late with this answer but since the problem is the binding you could do this step later with the help of a templated version for your callback registration function and another one for regular function pointers:
template<typename C>
void RegisterCallback(void (C::* func)(int, bool), C* inst)
{
MyCallback callback(boost::bind(func, inst, _1,_2));
}
void RegisterCallback(void (*func)(int, bool))
{
MyCallback callback(func);
}
A * myA = new A();
RegisterCallback(&A::GoodCallback, myA);
RegisterCallback(&A::BadCallback, myA); // DOES NOT COMPILE
RegisterCallback(GoodCallback);
RegisterCallback(BadCallback); // DOES NOT COMPILE
This works as expected in VS2010 but has the disavantage of needing not one but two callback registration functions to correctly deal with member and non-member functions.
As another option you might have a look at the boost function_types library. It provides a parameter_types metafunction that extracts the parameter types of function pointers and returns them as a MPL sequence. Then with a bit template magic it's possible to validate the parameters of the callback function, something like:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/equal.hpp>
using namespace boost;
using namespace boost::function_types;
template< typename Function >
void RegisterCallback(Function f)
{
BOOST_MPL_ASSERT((
mpl::equal<
parameter_types< Function >,
parameter_types< void(int,bool) >
>
));
MyCallback callback(f);
}
template<typename Function, typename T>
void RegisterCallback(Function f, T* inst)
{
BOOST_MPL_ASSERT((
mpl::equal<
parameter_types< Function >,
parameter_types< void (T::*)(int,bool) >
>
));
MyCallback callback(boost::bind(f, inst, _1, _2));
}
This also works as expected in VS2010 but you still need two function declarations although it should be possible to pack them in one if you define them inside a struct (and use a default template parameter argument for T);