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
Polymorphic_Allocator: When and Why Should I Use It
Lambda Capture as Const Reference
How Bad Is Redefining/Shadowing a Local Variable
C++ Error: '_Mm_Sin_Ps' Was Not Declared in This Scope
How to Output the Value of an Enum Class in C++11
Why How to Use 'Std::Move' on a 'Const' Object
Typeid' Versus 'Typeof' in C++
How to Convert a Char Array to a String
C++ Inherit from Multiple Base Classes with the Same Virtual Function Name
Libpng, Palette Png with Alpha or Not
Understanding the Example on Lvalue-To-Rvalue Conversion
Is There Still a Use for Inline
Multiset, Map and Hash Map Complexity
What Is the Best Modern C++ Approach to Construct and Manipulate a 2D Array
Why Is the C++ Stl Is So Heavily Based on Templates? (And Not on *Interfaces*)