Get Function Pointer from Std::Function When Using Std::Bind

convert std::bind to function pointer

Is there any way I can pass the member to the function?

Unless your class object is some kind of global object - it is not possible. Because objects may contain some data, while function pointer is just pointer to function - it doesn't contain any runtime context, only compile-time one.

If you accept having compile-time unique IDs for each callback passing, then you can use following generalized approach.

Usage:

void test(void (*fptr)())
{
fptr();
}

struct SomeStruct
{
int data;
void some_method()
{
cout << data << endl;
}
void another_method()
{
cout << -data << endl;
}
};

int main()
{
SomeStruct local[] = { {11}, {22}, {33} };

test(get_wrapper<0>( boost::bind(&SomeStruct::some_method,local[0]) ));
test(get_wrapper<1>( boost::bind(&SomeStruct::another_method,local[0]) ));

test(get_wrapper<2>( boost::bind(&SomeStruct::some_method,local[1]) ));
test(get_wrapper<3>( boost::bind(&SomeStruct::another_method,local[1]) ));

test(get_wrapper<4>( boost::bind(&SomeStruct::some_method,local[2]) ));
test(get_wrapper<5>( boost::bind(&SomeStruct::another_method,local[2]) ));
}

It may not require Unique ID's for each invocation, for instance because Functors may already have different types, or runtime scope of their usage do not overlap. But it is safer to use unique ID each time.

Implementation:

live demo

#include <boost/optional.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <ostream>
using namespace std;

template<unsigned ID,typename Functor>
boost::optional<Functor> &get_local()
{
static boost::optional<Functor> local;
return local;
}

template<unsigned ID,typename Functor>
typename Functor::result_type wrapper()
{
return get_local<ID,Functor>().get()();
}

template<typename ReturnType>
struct Func
{
typedef ReturnType (*type)();
};

template<unsigned ID,typename Functor>
typename Func<typename Functor::result_type>::type get_wrapper(Functor f)
{
(get_local<ID,Functor>()) = f;
return wrapper<ID,Functor>;
}

// ----------------------------------------------------------------------

void test(void (*fptr)())
{
fptr();
}

struct SomeStruct
{
int data;
void some_method()
{
cout << data << endl;
}
void another_method()
{
cout << -data << endl;
}
};

int main()
{
SomeStruct local[] = { {11}, {22}, {33} };

test(get_wrapper<0>( boost::bind(&SomeStruct::some_method,local[0]) ));
test(get_wrapper<1>( boost::bind(&SomeStruct::another_method,local[0]) ));

test(get_wrapper<2>( boost::bind(&SomeStruct::some_method,local[1]) ));
test(get_wrapper<3>( boost::bind(&SomeStruct::another_method,local[1]) ));

test(get_wrapper<4>( boost::bind(&SomeStruct::some_method,local[2]) ));
test(get_wrapper<5>( boost::bind(&SomeStruct::another_method,local[2]) ));
}

P.S. Beaware of multi-thread access - in such cases you should use some kind of Thread-local storage data.

Can I use std::bind to convert a pointer to member function into a pointer to function?

NathanOliver's comment is correct, and your suspicion is mostly correct. Exactly how pointers to member functions work is not specified, but including this as a hidden argument mostly works. You just need a bit of extra work for inheritance and pointers to virtual functions (yes, you can take their address too).

Now, often callbacks include a void* parameter under your control, which you can use to pass a A*. In those cases, you can write a wrapper (static) function that casts the void* back to A* and does the actual call to &A::callback.

That's not the case here. Registration takes a single function, without data. To get this to work in real-life situations, you have to resort to drastic solutions - not portable C++. One such method is to dynamically generate assembly (!). You create - at runtime - the compiled equivalent of

void __trampoline_0x018810000 (int i)
{
A* __this = reinterpret_cast<A*>(0x018810000);
__this->callback(i);
}

As you can see, you have to generate one trampoline for every A* value, and managing lifetimes of these is a major pain.

C++ 11 get pointer of a std::function

I want to store and identify std::function objects in a std::map.

I assume, you want to identify std::function objects (e.g. to call or delete them selectively).
In such situations, I use an additional key e.g. a simple unsigned.
A global function may be used:

typedef unsigned Key;

Key genId()
{
static Key id = 0;
return ++id;
}

Now, the std::function objects can be paired with this key. The API may grant that access to paired std::function objects can be done using the key exclusively.

Get function pointer from std::function when using std::bind

This is quite impossible. The whole reason that std::function exists is that function pointers suck horrifically and should never, ever, be used by anyone, ever again, except for the doomed souls bearing the Burning Standards of Hell C interoperation, because they cannot handle functions with state.

A std::function<void()> cannot, in the general case, be converted to a void(*)(). The only reason this works in the first example is because it happens to be a void(*)() originally.

Use std::bind and store into a std:: function

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);

Get address of member function through std::bind?

You should switch to using std::function instead (update: it turns out you did already). std::function is a general-purpose polymorphic function wrapper that will accept raw function pointers, binds, etc.
That way you have a standardized way to compare, which you need to pull off somehow but std::function has ways to inspect the target, etc. : https://en.cppreference.com/w/cpp/utility/functional/function

Your signature becomes:

EventObject<Ts...>& operator-=(const std::function<R(Args...)>& rhs) {

Update: the issue with your target extraction is that you provide the signature of a plain function as the template argument - this will not work for the more 'advanced' function objects, binds etc. you have to provide the correct type so that:

target_type() == typeid(T)

see https://en.cppreference.com/w/cpp/utility/functional/function/target for more information and some relevant examples

How to insert std:bind as function pointer into constant map

As was stated in comments, std::bind returns callable object - it is unnamed class which has operator()(args) and it cannot be casted to pointer to function. You need to use std::function as wrapper.

Another issue, string is bound when std::bind is called, so final functor will take only int*, typedef for funcptr may be:

typedef std::function< std::pair<int,int>(int*) > funcptr;


Related Topics



Leave a reply



Submit