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
Related
I want to bind a static member function to a boost::function using boost::bind. The following is an example of what I want to do (not working).
class Foo {
public:
static void DoStuff(int param)
{
// To do when calling back
}
};
class Question {
public:
void Setup()
{
AssignCallback(boost::bind(&Foo::DoStuff, _1)); // How to bind the static funciton here
}
void AssignCallback(boost::function<void(int param)> doStuffHandler)
{
...
...
}
};
I have previously used boost::bind with member functions using this syntax:
boost::bind(&Foo::NonStaticMember, this, _1, _2, _3, _4)
But this is obviously not correct for a static member.
Can you please explain to me how to correctly bind a static member function of a class using boost::bind?
It will be done as you do for normal functions binding.
For static function you just need to use its class name for to recognize the function by the compiler and skip the this argument since static finctions are bound to class not to the object.
Below is a simple example:
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
void test(boost::function<bool(int, int)> func)
{
std::cout<<"in test().\n";
bool ret = func(10, 20);
std::cout<<"Ret:"<<ret<<"\n";
}
class Test
{
public:
static bool test2(int a, int b)
{
std::cout<<"in test2().\n";
return a>b;
}
};
int main()
{
test(boost::bind(&Test::test2, _1, _2));
return 0;
}
O/P:
in test().
in test2().
Ret:0
You should not use this as static functions dont have this pointer.
int main()
{
test(boost::bind(&Test::test2, this, _1, _2));-----> Illegal
return 0;
}
Below error will occur:
techie#gateway1:myExperiments$ g++ boost_bind.cpp
boost_bind.cpp: In function âint main()â:
boost_bind.cpp:26: error: invalid use of âthisâ in non-member function
Hope this will help. :-)
Your code is correct. Maybe you experience some compiler issue? Can you cite the compilation output?
You can also try using std::function and std::bind instead. Only replace boost headers with "functional" header and write
std::placeholders::_1
instead of
_1
I want to create a boost function object of the following signature:
void (int, boost::uuid);
However, I would like to bind it to a function of the following form:
void (SomeType, boost::uuid)
Where the SomeType argument comes from another function call, so that if I were to call it straight out it would look like:
SomeType myOtherFunction(int);//Prototype
...
myFunction(myOtherFunction(int), myUUID);
In other words, I want the top level function object to completely hide the concept of SomeType and the call to myOtherFunction from the user. Is there a way to do this with one or more boost::function objects created with boost::bind calls?
Functional composition: Live On Coliru
#include <boost/uuid/uuid.hpp>
struct SomeType {};
SomeType myOtherFunction(int) { return SomeType(); }
void foo(SomeType, boost::uuids::uuid) {}
#include <boost/bind.hpp>
#include <boost/function.hpp>
int main()
{
boost::function<void(int, boost::uuids::uuid)> composed;
composed = boost::bind(foo, boost::bind(myOtherFunction, _1), _2);
}
Anyways, in c++11 you'd write [](int i, uuid u) { return foo(myOtherFunction(i), u); } of course
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.
I can easily bind member functions to a std::function by wrapping them with a lambda expression with capture clause.
class Class
{
Class()
{
Register([=](int n){ Function(n); });
}
void Register(std::function<void(int)> Callback)
{
}
void Function(int Number)
{
}
};
But I want to bind them directly, something like the following.
// ...
Register(&Class::Function);
// ...
I think according to the C++11 standard, this should be supported. However, in Visual Studio 11 I get these compiler errors.
error C2440: 'newline' : cannot convert from 'int' to 'Class *'
error C2647: '.*' : cannot dereference a 'void (__thiscall Class::* )(int)' on a 'int'
I think according to the C++11 standard, this should be supported
Not really, because a non-static member function has an implicit first parameter of type (cv-qualified) YourType*, so in this case it does not match void(int). Hence the need for std::bind:
Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1));
For example
Class c;
using namespace std::placeholders; // for _1, _2 etc.
c.Register(std::bind(&Class::Function, &c, _1));
Edit You mention that this is to be called with the same Class instance. In that case, you can use a simple non-member function:
void foo(int n)
{
theClassInstance.Function(n);
}
then
Class c;
c.Register(foo);
According to Stephan T. Lavavej - "Avoid using bind(), ..., use lambdas".
https://www.youtube.com/watch?v=zt7ThwVfap0&t=32m20s
In this case:
Class()
{
Register([this](int n){ Function(n); });
}
You can use std::bind:
using namespace std::placeholders; // For _1 in the bind call
// ...
Register(std::bind(&Class::Function, this, _1));
In C++ 17, you can use:
Register([=](auto && ...args){ return Function(args...); });
which is sweet especially if the argument list is longer long.
Of course the member function's argument list must then be compatible with the std::function's ones.
With std::function and std::bind, you can treat different class member function the same.
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
using namespace std::placeholders;
class Foo
{
public:
void foo(const string &msg)
{
cout << msg << '\n';
}
};
class Bar
{
public:
void bar(const string &msg, const string &suffix)
{
cout << msg << suffix << '\n';
}
};
int main(int argc, char **argv)
{
Foo foo;
Bar bar;
vector<function<void (const string &msg)>> collection;
collection.push_back(bind(&Foo::foo, &foo, _1));
collection.push_back(bind(&Bar::bar, &bar, _1, "bar"));
for (auto f : collection) {
f("foo");
}
return 0;
}
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);