I try this : timer tuto.
But the void print is in another class. When i call the function in main:
t.async_wait(&class::print);
I have this error :
error : must use '.*' or '->*' to call pointer-to-member function in 'boost::asio::detail::lvref<void (class::*)(const boost::system::error_code&)>() (...)', e.g. '(... ->* boost::asio::detail::lvref<void (class::*)(const boost::system::error_code&)>())
I don't know how fix this issue :s
You will have to bind the object instance, like: t.async_wait(boost::bind(&Class::print, this, _1)); Or if the instance is not this, use another (smart) pointer that points to a Class. You can use a reference, but that requires a reference wrapper to prevent bind from copying the bound argument: Class c;
// ...
t.async_wait(boost::bind(&Class::print, boost::ref(c), _1));
I have already tried, but I have an error :
error : 'void (class::*)(const boost::system::error_code&)' is not a class, struct, or union type typedef typename F::result_type type;
You need to handle the parameter that the print method expects.
Something like this:
t->async_wait(boost::bind(&Class::print, this,
boost::asio::placeholders::error));
Take a look at this tutorial http://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/tutorial/tuttimer3.html
I try but I have an error which i don't understand
error : pointer to member type 'void (class::)(const boost::system::error_code&)' incompatible with object type 'windows'
BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1);
^
You will have to bind the object instance, like:
t.async_wait(boost::bind(&Class::print, this, _1));
Or if the instance is not this, use another (smart) pointer that points to a Class. You can use a reference, but that requires a reference wrapper to prevent bind from copying the bound argument:
Class c;
// ...
t.async_wait(boost::bind(&Class::print, boost::ref(c), _1));
You need to handle the parameter that the print method expects.
Something like this:
t->async_wait(boost::bind(&Class::print, this,
boost::asio::placeholders::error));
Take a look at this tutorial http://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/tutorial/tuttimer3.html
Related
I have the following code which used std::bind :
EventListenerCustom* _createNewObjectlistener =
eventDispatcher->addCustomEventListener(Constants::MY_EVENT,
std::bind(&MyClass::MyFunction, this, std::placeholders::_1));
It seems I create many different kinds of object listeners, where the only difference is the event, and the function being called. If I wanted to encapsulate the above code into a function:
How would I pass MyClass::MyFunction as an argument to the function ?
What would the function signature and parameters look like ?
I imagine the function would look something like this:
EventListenerCustom* MyFunc(<What Goes Here> functionToBeBound,<What goes here> object,std::string EVENT){
EventListenerCustom* eventListener = eventDispatcher->addCustomEventListener(EVENT, std::bind(functionToBeBound, object, std::placeholders::_1));
return eventListener;
}
What should the function look like ? And How do I call it? What would the calling code look like?
EDIT: Concrete details:
I have many listener objects which are created in identical ways:
auto eventDispatcher = _dragNode->getEventDispatcher();
_createNewObjectlistener = eventDispatcher->addCustomEventListener(Constants::MY_EVENT, std::bind(&MyClass::myOtherFunction, this, std::placeholders::_1));
_moveNewObjectlistener = eventDispatcher->addCustomEventListener(Constants::MY_EVENT2 std::bind(&MyClass::myFunction, this, std::placeholders::_1));
Constants::MY_EVENT etc are just const char* .
The only difference is the Function being called, and the string constant used as an event name. How can I encapsulate this into a function ? I have tried John Zwinck's solution below, but for some reason I can't get it to compile because the compiler complains:
: No viable conversion from '__bind<void (*&)(cocos2d::EventCustom *), MyNameSpace::MyClass *, const std::__1::placeholders::__ph<1> &>' to 'const std::function<void (EventCustom *)>'
To make it simpler, create a typedef for a pointer to any member function in MyClass which has the appropriate signature:
typedef void (MyClass::*MyMemberFn)(int); // replace int and void as needed
Then:
EventListenerCustom* MyFunc(MyMemberFn functionToBeBound, MyClass* object, std::string EVENT){
return eventDispatcher->addCustomEventListener(EVENT, std::bind(functionToBeBound, object, std::placeholders::_1));
}
What you're really looking for is std::function. The documentation for such is here: https://en.cppreference.com/w/cpp/utility/functional/function
Their example is really good at explaining how it's used, but for your case (or related) try this:
std::function<void(int)> func1 = std::bind(MyClass::MyFunction, this, std::placeholders::_1));
What this will do is create an object which can be called, and the first argument is forwarded on to the first argument of the member function, both of which should be int type, and it returns nothing. You don't actually need address-of operator for the function name.
The cool part here is that the object returned by std::bind can be passed into the constructor of std::function and all its information is preserved. So when you need a concrete type that can be copied and all that cool stuff (passed into a function NOT by reference for example) then use a std::function as it will do the job, as long as it's not trying to copy a non-copyable type or something. std::function can also be initialized with a function pointer. It's generally just "better" than function pointers for C++, especially combined with std::bind to handle classes.
I could write out more examples, but check out the link above, and check out std::bind on that same website. Both should help.
I am trying to bind std::function with derived argument. Function I want to bind looks like this:
void Application::myFunction(Derived *derived) { }
Function I am trying to pass into this function (but bound) looks like this:
void Storage::register(int number, std::function<void(Base *base)>) { }
And I am doing this (this keyword in this context is Application):
myStorage->register(0, std::bind(&Application::myFunction, this, std::placeholders::_1);
But that gives me error:
error: no matching function for call (Storage::register...)
Any idea what am I doing wrong? Thank you!
This does not work because std::function<void(Base*)> does not guarantee that it will always be called with a Derived*. You cannot do this anymore than you can call Application::myFunction with a Base* directly.
Depending on what it is you want to achieve, make it a std::function<void(Derived *)> or have myFunction work with Base*.
I'm trying to create an array of function pointers in C++ that I can use as a jump table. The functions are all prototyped like
void(unsigned char*, int, int)
So I thought I would do
typedef void (*func)(unsighed char*, int, int);
and then
func tfunc[256];
And then set the individual elements like this:
tfunc[0]=func01;
But then I get "function call missing argument list; use '&myclass::func01'"
But then when I try
tfunc[0]=&myclass::func0;
I get "error C2440: '=' : cannot convert from 'void (__thiscall myclass::* )(unsigned char *,int,int)' to 'myclass::tfunc'
1> There is no context in which this conversion is possible
I am confused.
I think I fixed it by adding MyClass:: in the header: tyepdef void (MyClass::*func...);
You could use std::function<void(unsigned char*, int, int)> for your array of functions and appropriately bind your object using std::bind():
using namespace std::placeholders;
std::function<void(unsigned char*, int, int)> tfunc[256];
tfunc[0] = std::bind(&myclass::func0, this, _1, _2, _3);
Using std::function<Signature> is nicer than using function pointers in all cases because it allows to pass through necessary context, e.g., a pointer to an object. If you really mean to just call the function and you don't need an object, you can still use std::function<...> and you made your func0 member static instead. In that case you could still use std::bind() but it isn't really needed:
struct myclass {
static void func0(unsigned char*, int, int);
};
// ...
tfunc[0] = std::bind(&myclass::func0, _1, _2, _3);
tfunc[0] = &myclass::func0;
For the fans of dynamic polymorphism: internally std::function<...> has an inheritance hierarchy and any concrete initialization instantiates a derived class as needed. The only real differences are that you don't need to faff about creating a hierarchy and some implementations do clever things to make it more efficient.
Even though you have an array of pointers to {static} functions or pointers to members, you will still need to pass the parameters when you call the function:
(*vector_of_functions[i])(param1, param2, param3);
The above is for standalone functions. Executing a member via pointer to member method is left as an exercise to the reader (hint: See C++ faq pointer to member).
If you want to put a class member function into your array, the class member function should be declared static.
In case your class member function is not static, than you have to "bind" this to it, and it forces you to use the solution suggested by #Dietmar.
So I have this function:
void EventDispatcher::Subscribe(string eventName, void (*callback)(void *))
{
....
}
I am trying to pass class member function as a callback parameter there.
typedef void (*method)(void*);
void EventTester::RunTests()
{
_dispatcher = new EventDispatcher();
Event eventOne("one");
_dispatcher->Register("one", eventOne);
method p = &onOne;
_dispatcher->Subscribe("one", p);
}
void EventTester::onOne(void *args)
{
std::cout<<"Event one\n";
}
obviously this doesn't compile because onOne is not static and a member function. Is there any way of making it work this way?
You could use boost in C++03 or std::bind and std::function in C++11:
typedef boost::function<void(void*)> func_type;
void EventDispatcher::Subscribe(const string& eventName, const func_type& func_)
{
if ( ! func_.empty() ) {
// you could call the function
func_(NULL);
}
}
//Register looks like in a member function of EventTester:
...
_dispatcher->Subscribe("one",boost::bind(&EventTester::onOne,this,_1));
...
I'm going off the assumption that you have the ability to modify the signature of Subscribe. If not, my answer may not apply.
As you already noted, your pointer-to-member (aka method) is not the same as a plain function pointer. To use a pointer-to-member, you have to supply the class instance to call the function on as part of the method execution.
You could modify Subscribe to explicitly take in a pointer-to-member, which would expect an additional argument (the class instance). You would need Subscribe to store both the function pointer, and a pointer to your object instance. This would then require that all callbacks be implemented as pointers-to-members.
The preferred way to solve this problem is to use bind (either std::bind or boost::bind).
You would need to change your Subscribe function to take in a std/boost::function object instead of an explicit function pointer. This would permit callers of the Subscribe method to pass in any callable object (See the examples in the documentation of std::function)
You can then use bind to connect your class instance to your method pointer. This will return a functor object which will do the work of holding both your pointer-to-member and a pointer to your class instance.
For an example of how to use bind, see this link
I have this problem with boost::thread that i cannot solve.
I have a classX.h file:
#include <boost/thread/thread.hpp>
class classX{
...
void startWork(void);
void doWork(void);
...
}
and then a .cpp file:
...
void classX::startWork(){
boost::thread(&doWork);
}
void classX::doWork(){
...
}
I cannot compile, i obtein the error (at the line in which i do boost::thread(&doWork)):
error C2761: 'void plsa_mt_2::doWork(void)' : member function redeclaration not allowed
Is this error related with the thread creation or with something else? What can i do to solve it?
Since classX::doWork() is a member function of classX, you can't call the member function pointer (&classX::doWork) without providing a pointer to a classX.
The Boostiest way to accomplish this is by using Boost Bind to create a callable functor with the member function pointer and a pointer to the classX, like so:
void classX::startWork() {
boost::thread t(boost::bind(&classX::doWork, this)); // be careful, the boost::thread will be destroyed when this function returns
}
You could alternatively make doWork() a static member function or a global function if doWork() doesn't need access to instance properties of the classX:
firstly, the correct syntax for getting a pointer to a member function is
&classX::doWork
However I tink you might not be showing the exact code yielding the error, because the typical error for &doWork in VS is
error C2276: '&' : illegal operation on bound member function expression