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);
Related
I'm trying to build a class made up by a vector of threads.
The class should have a method that take as argument another function, this function has to be executed by a new threads.
I would like to avoid use of native pointer, so I'm not excatly sure how to build this specific method.
You can pass a function like this:
template <typename F>
void call_function(F f) {
f();
}
For example:
#include <iostream>
void sayHello() {
std::cout << "Hello\n";
}
int main() {
call_function(sayHello);
}
regarding your constraints I suggest to use std::function. You can then use std::bind and if using C++20, std::bind_front.
cheers,
FM.
I have a slightly convoluted use case of passing a member function pointer to an outside function which is then called again by a member function (Don't ask!). I'm learning about std::function and std::mem_fn but I can't seem to be able to convert my old school function pointer
void (T::*func)(int) to a std::function<void (T::*)(int) func>
in the code below, I'd like to be able to pass a std::function to memFuncTaker in the call from anotherMember
#include "class2.hpp"
#include <iostream>
class outer{
public:
void aMember(int a){
std::cout << a <<std::endl;
}
void anotherMember(double){
memFuncTaker(this, &outer::aMember);
}
};
template<class T>
void memFuncTaker(T* obj , void (T::*func)(int) ){
(obj->*func)(7);
}
When you bind std::function to a non-static member function pointer, it "reveals" the hidden this parameter, making it the first explicit parameter of the resultant functor. So in your case for outer::aMember you'd use std::function<void(outer *, int)> and end up with a two-parameter functor
#include <functional>
#include <iostream>
template<class T>
void memFuncTaker(T *obj , std::function<void(T *, int)> func){
func(obj, 7);
}
class outer{
public:
void aMember(int a){
std::cout << a <<std::endl;
}
void anotherMember(double){
memFuncTaker(this, std::function<void(outer *, int)>{&outer::aMember});
}
};
int main() {
outer o;
o.anotherMember(0);
}
http://coliru.stacked-crooked.com/a/5e9d2486c4c45138
Of course, if you prefer, you can bind the first argument of that functor (by using std::bind or lambda) and thus "hide" it again
#include <functional>
#include <iostream>
using namespace std::placeholders;
void memFuncTaker(std::function<void(int)> func){
func(7);
}
class outer{
public:
void aMember(int a){
std::cout << a <<std::endl;
}
void anotherMember(double){
memFuncTaker(std::function<void(int)>(std::bind(&outer::aMember, this, _1)));
}
};
int main() {
outer o;
o.anotherMember(0);
}
Note that in this version memFuncTaker no longer has to be a template (which happens to be one of the primary purposes of std::function - employ type erasure techniques to "de-templatize" the code).
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
I've managed to figure out how to use std::bind to replace a whole bunch of code that previously triggered C-style callbacks (not shown here) via a web of static variables, static functions, and a compiler extension __closure.
This code compiles and runs successfully; however, in trying to make a slight improvement I get a weird compiler error.
#include <iostream>
#include <string>
#include <functional>
typedef void MyFunc(std::string &);
struct Master
{
void func(std::string &s) { std::cout << "Master::func(" << s << ")\n"; }
void go();
Master() {}
private:
Master(Master const &);
};
int main()
{
Master m;
m.go();
}
void call_function( std::function<MyFunc> fp, std::string s )
{
fp(s);
}
template<typename FuncT, typename Host>
typename std::function<FuncT> my_binder(Host *h, FuncT Host::*p)
{
using std::placeholders::_1;
return std::bind(p, h, _1);
}
void Master::go()
{
std::string s("hello");
// OK
using std::placeholders::_1;
std::function<MyFunc> f = std::bind(&Master::func, this, _1);
call_function(f, s);
call_function( std::bind(&Master::func, this, _1), s );
// Undefined structure 'boost::function<void(std::string &)>'
my_binder(this, &Master::func);
// I'm hoping to end up here
// call_function( my_binder(this, &Master::func), s );
}
The code appears to work in latest g++ and clang, but gives
// Undefined structure 'boost::function<void(std::string &)>'
on another compiler which has not-quite-c++11 support. Is my code correct (i.e. the failing compiler has a bug)?
Also: is there a pre-existing template I can use instead of my_binder? My aim is to make it so that people can call call_function as easily as possible, without having to muck around with including std::placeholders and so on. Of course this is possible with a preprocessor macro but it'd be nice to use a template function.