Function Pointers as Event Callbacks in a st - c++

I am currently trying to implement an event system where layers can subscribe to certain event types. I am struggling with function pointers for the callback methods. In the layer.h file I have the OnEvent function and a function pointer which looks like this:
void OnEvent(const Event& e);
void(Engine::Layer::*m_EventCallback)(const Event& e);
In the constructor of a layer I simply do this:
m_EventCallback = OnEvent;
To keep track of which layer subscribed to which EventType I have defined a struct as folling:
struct CallbackData {
EventType type;
void(Engine::Layer::*OnEvent)(const Event& e);
int layerID;
bool isActive;
};
I have an EventDispatcher and its dispatch function looks something like this:
bool EventDispatcher::Dispatch(const Event& e)
{
for (CallbackData& calldata : m_Callbacks) {
if (calldata.type == e.GetEventType() && calldata.isActive) {
calldata.OnEvent(e);
}
}
//TODO work on this so it only returns true if the event has been properly dispatched
return true;
}
There is also a subscribe function which creates an instance of CallbackData and pushes it into a vector which looks like this:
void EventDispatcher::Subscribe(EventType type, void(Engine::Layer::*OnEvent)
(const Event& e), int layerID)
{
CallbackData temp = { type, OnEvent, layerID, true };
m_CallbackInsert = m_Callbacks.emplace(m_CallbackInsert, temp);
}
So if the type is of callback data is the same as the event references type the OnEvent function should get called via the function pointer.
The function pointer defintion needs to have Engine:: which is just a namespace and Layer which is the class where the OnEvent lies. I dont know why it needs the namespace because everything I do here is defined in the namespace.
But the main question is how do I properly define the function pointer and then call it the way showcased here?
The exact error message is this:
expression preceding parentheses of apparent call must have(pointer-to-)function type
Please dont link sites with already implemented event systems. I have already looked at those and didnt really understand much. Thats why I want to do it myself so I do understand it.
Thanks in advance!

Assuming I understand what you're doing...
You have an EventDispatcher, and he needs to keep a registry of possible callbacks to make. I'm going to cut & paste a little code I use then explain it.
First, this is the relevant portion of my Route object.
class Route {
public:
typedef std::function<void(const HTTPServerRequest &, HTTPServerResponse &)> Callback;
Callback callback;
};
class Router {
public:
void addRoute(const std::string &method, const std::string &path, Route::Callback callback);
};
That part works about how you would expect and doesn't require anything special. This creates an array of Route objects, with the callback method being given the callback passed into addRoute(). When I want to dispatch on this particular route:
route->callback(request, response);
You probably know that part, too.
For my code, I'm making method calls into an object. To pass that, you have two choices. The first is to use std::bind() -- which I really dislike.
So I use lambdas.
addRoute("GET", "/ping", [=](const HTTPServerRequest &request, HTTPServerResponse &response) { ping(request, response); } );
Is this absolutely the most efficient? I have no idea. But performance isn't ultra-sucky, so this is what I do.
Basically, I keep std::function<> pointers, and those are really easy to use. You can pass a lambda as a std::function<> as long as the signature matches.
The other choice is to use std::bind -- which, as I said, I don't like, mostly because I think it's uglier than using a lambda. But that's definitely an opinion, not a fact. Using std::bind may be a better way, but I don't have any code to show you doing it that way.
I'm not entirely sure this actually solves the confusion you're having, but if it's close, just comment, and I'll try to clarify.

Related

Factory pattern and std::bind methods

I've implemented a factory pattern in C++ some weeks ago using the following guide : https://www.codeproject.com/Articles/363338/Factory-Pattern-in-Cplusplus
Since then it worked well: all of the methods used in the factory pattern were returning the same type, and were also taking the same arguments types, until today. I now need to add bind new arguments to the methods I use, so methods signatures are not the same anymore.
I am currentyl using 2 things, and implementing a third one :
1) Actions: each represented as a class and containing a static AAction::ptr create(void* buff) method. Actions inherits from AAction class. Actions can be serialized using their own serialize() internal method, or deserialized using their create(buff) static method.
The buffer argument contains the id and password necessary to call the LoginAction() constructor.
class AAction {
typedef std::unique_ptr<AAction> ptr;
};
class LoginAction : public AAction {
private:
std::string id;
std::string password;
bool authenticated;
public:
LoginAction(std::string id, std::string password);
virtual ~LoginAction() = default;
void execute();
static AAction::ptr create(const void* buffer);
};
2) ActionFactory: used to deserialize incoming actions, by calling the appropriate create() static method from the correct class.
class ActionFactory {
typedef std::unique_ptr<AAction> (*CreateActionFn)(const void*);
typedef std::map<RawActionType, CreateActionFn> RawFactoryMap;
RawFactoryMap rawFactoryMap;
public:
ActionFactory(Authenticator& authenticator) {
this->registerMethod(RawActionType_RawLoginAction, &LoginAction::create);
this->registerMethod(RawActionType_RawLogoutAction, &LogoutAction::create);
this->registerMethod(RawActionType_RawStandAction, &StandAction::create);
}
void registerMethod(const RawActionType &rawActionType, CreateActionFn pfnCreate);
std::unique_ptr<AAction> getAction(RawActionType rawActionType, const void* buffer);
};
Actions can be executed at any time in the code, by simply calling the execute() method, with no parameters.
Up to this point, eveything works fine.
The issue is that I now need to add some more parameters to actions that are not stored inside the password. For example in my case: an Authenticator
3) An Authenticator, to authenticate a user.
So that inside LoginAction::execute(), all I have to do is call
this->authenticator.authenticate(this->id, this->password).
Here are the changes I made for that :
I added authenticator to the LoginAction constructor :
LoginAction(Authenticator& authenticator, std::string id, std::string password);
And a field :
Authenticator& authenticator;
I added authenticator to the LoginAction::create static method :
static AAction::ptr create(const void* buffer, Authenticator& authenticator);
I modified, inside the ActionFactory constructor, the way I register method, using std::bind :
this->registerMethod(RawActions_RawLoginAction, std::bind(&LoginAction::create, std::placeholders::_1, authenticator);
But, as my function types have changed, I cannot store it in the RawFactoryMap anymore.
error: invalid cast from type ‘std::_Bind_helper ()(const void, Authenticator&), const
std::_Placeholder<1>&, Authenticator&>::type {aka
std::_Bind ((std::_Placeholder<1>,
Authenticator))(const void, Authenticator&)>}’ to type
‘ActionFactory::CreateActionFn {aka std::unique_ptr ()(const
void)}’
What is the best way to proceed, to keep a map of functions in the ActionFactory and respect the Factory pattern ?
Thanks in advance, and have a good day!
As an additional note: I am open and would be glad to read any suggestion on how to improve my code, even for some minor improvements.
First things first. With C++11, strongly prefer using to typedef. Consider the difference in readability between:
typedef std::unique_ptr<AAction> (*CreateActionFn)(const void*);
typedef std::map<RawActionType, CreateActionFn> RawFactoryMap;
and:
using CreateActionFn = std::unique_ptr<AAction>(*)(const void*);
using RawFactoryMap = std::map<RawActionType, CreateActionFn>;
It's nice when the names appear on the left instead of in an arbitrary location.
That said, now that function pointers are insufficient because you need to store state, you need to generalize to an arbitrary callable. That's what std::function is for: a type-erased callable of the provided signature:
using CreateActionFn = std::function<std::unique_ptr<AAction>(const void*)>;
This will match any callable that is copyable and which you can invoke with a const void* and get a unique_ptr<AAction>.
And while we're here, don't use std::bind:
std::bind(&LoginAction::create, std::placeholders::_1, authenticator)
use a lambda:
[authenticator](void const* ptr){ return LoginAction::create(ptr, authenticator); }
or:
[=](void const* ptr){ return LoginAction::create(ptr, authenticator); }
It may not be shorter, but it's quite a bit easier to read.

How to get a general function pointer as a private member of a C++ class?

In the game I'm making, there will be triggers. When the trigger collides with anything, something will happen; If it is a door trigger, then the player will get moved to a new area. If it's an explosion trigger, and explosion happens. A chair trigger may make the player sit down.
I don't want to subclass each and every trigger. Each one shares enough important info, and each would activate using a common interface. The only difference between them is the routine that is called on collision.
The problem is the functions themselves may have differing signatures.
For example, the move player function requires a few things.
void move_player(Environment *new_env, Player *player, int new_x, int new_y)
But an explosion trigger may just be
void explode()
I need a class that accepts a move_player and a explode.
Here's what I think the pseudo code should look like
class Trigger
{
public:
Trigger(function_pointer f) { fp = f; }
void activate() { fp(); }
private:
func_pointer fp;
}
I was thinking initializing/using it would look something like this.
auto f = std::bind(move_player, new_environment, my_player, 0, 0);
Trigger tigger (f);
tigger.activate();
I've tried going into std documentation and searching around other forums, along with checking out Boost documentation. I know how to use bind, and I'm pretty sure it should work here, but I have no how to set up the function pointer within the class to be of one indifferent to argument lists. A minimum working example would be awesome.
You could use std::function in combination with std::bind and variadic templates like the example below:
class Trigger {
std::function<void()> fp;
public:
template<typename F, typename ...Args>
Trigger(F f, Args... args) : fp(std::bind(f, args...)) { }
void activate() { fp(); }
};
LIVE DEMO
What you want to use here is std::function. More concretely, an std::function<void()>. Also consider using a lambda instead of bind:
auto f = [=]() { movie_player(new_environment, my_player, 0, 0); };
Whilst it may be possible to solve this using std::function and std::bind and/or lambda functions, that's just compiler and template magic for creating your own class - if you are keen on template magic, then by all means go for it. But I find that it doesn't really solve any problem [that needs solving], and makes the code harder to follow and debug (because you WILL sooner or later want to debug your move player trigger, most likely - at least unless you are a MUCH cleverer person than me and can write code that NEVER needs debugging). Setting a breakpoint in std::function::operator() is quite hard to get right and only break when you want, and not when it's called from some other place (e.g. your std::string lower-case converting function that deals with the user-input). .
In this case, I'd say a Trigger class with a virtual function would be the right thing.
The MovePlayer [or if you want to call it move_player] class would perhaps look like this:
class MovePlayer : public Trigger
{
MovePlayer(Player *p, int x, int y) : player(p), dx, dy) {}
void Activate() override { player->SetPos(dx, dy); }
private:
Player *player;
int dx, dy;
};
[Of course, you should not use raw pointers - in this case, use std::shared_ptr<Player> and store std::weak_ptr<Player> in your MovePlayer]

Function pointer to a non-static member function when the class type is unknown?

I'm working on a game project that features scratch-built controls rendered into an opengl context; things like buttons, scrollbars, listboxes, etc. Many of these controls are nested; for example, my listbox has a scrollbar, a scrollbar has 3 buttons, etc.
When a scrollbar changes value, I'd like it to call 'some' function (typically in it's parent object) that responds to the change. For example, if the listbox has a slider, it should instantiate the slider, then tell the new slider that it should call the listboxes 'onScroll(float)' function. All of the controls share a common base class, so I could have a 'base* parent' parent pointer, then do 'parent->onScroll(val)'. The problem though is what happens when the parent doesn't inheirit from base; there'd be no virtual onScroll() to follow through, so the top-level parent would have to periodically check to see if any of the child controls had changed value. This would also clutter up other controls, since they may not even have children, or may require different event types like when a list entry object is selected, etc.
A better solution would be to have the child object maintain a generic function pointer (like a callback), which can be set by the parent, and called by the child as necessary. Something like this:
typedef (*ptFuncF)(float);
class glBase {
public:
//position,isVisible,virtual mouseDown(x,y),etc
};
class glDerivedChild : public glBase {
public:
glDerivedChild();
~glDerivedChild();
void changeValue(float fIn) {
Value = fIn; //ignore these forward declaration errors
(*callBack)(fIn);
}
void setCallBack(ptFuncF pIn) {callBack = pIn;}
ptFuncF callBack;
float Value;
};
class glDerivedParent : public glBase {
public:
glDerivedParent() {
child = new glDerivedChild();
child->setCallBack(&onScroll);
}
~glDerivedParent() {delete child;}
void onScroll(float fIn) {
//do something
}
glDerivedChild* child;
};
class someFoo {
public:
someFoo() {
child->setCallBack(&setValue);
}
void setValue(float fIn) {
//do something else
}
glDerivedChild child;
};
I'm kinda new to function pointers, so I know I'm (obviously) doing many things wrong. I suspect it might involve something like "typedef (glBase::*ptFuncF)(float);" with the 'onScroll(f)' being an overridden virtual function, perhaps with a generic name like 'virtual void childCallBack(float)'. I'd prefer to keep the solution as close to vanilla as possible, so I want to avoid external libraries like boost. I've been scratching my head over this one for the better part of 8 hours, and I'm hoping someone can help. Thanks!
I think, what you want is some kind of events or signals mechanism.
You can study, how event processing is organized on Windows, for example. In short, your scrollbar generates new event in the system and then system propagates it to all elements, registered in the system.
More convenient mechanism is signal/slot mechanism. Boost or Qt provides such tools. I'll recomend this solution.
But if you still want to use just callbacks, I'll recommend using std::function (boost::function) (combined with std::bind (boost::bind), when required) instead of raw function pointers.
Use boost::function (or std::function if available). Like this (using your notation):
typedef std::function<void (float)> ptFuncF;
//...
void setCallBack(const ptFuncF &pIn);
//...
child->setCallBack(std::bind(&glDerivedParent::onScroll, this, _1));
//...
child->setCallBack(std::bind(&someFoo::setValue, this, _1));
A function pointer to a member function of a class has such a type:
<return type> (<class name>::*)(<arguments>)
For example:
typedef void (glBase::*ptFuncF)(float);
^^^^
by the way, you have forgot the `void` in your `typedef`
ptFuncF func = &glDerivedChild::onScroll;
And you use it like this:
glDerivedChild c;
(c.*func)(1.2);
In your particular example, the function is a member of the derived class itself, therefore you should call it like this:
(c.*c.callback)(1.2);
the inner c.callback is the function pointer. The rest is exactly as above, which is:
(class_instance.*function_pointer)(arguments);
You might want to take a look at this question also.
Ok, the workaround I came up with has some extra overhead and branching, but is otherwise reasonable.
Basically, each callback function is implemented as a virtual member function that recieves the needed parameters including a void* pointer to the object that made the call. Each derived object also has a base-class pointer that refers to the object that should recieve any events that it emits (typically its parent, but could be any object that inheirits from the base class). In case the control has multiple children, the callback function uses the void* pointer to distinguish between them. Here's an example:
class glBase {
public:
virtual onChildCallback(float fIn, void* caller);
glBase* parent;
};
class glSlider : public glBase {
public:
glSlider(glBase* parentIn);
void changeValue(float fIn) {
Value = fIn;
parent->onChildCallback(fIn, this);
}
float Value;
};
class glButton : public glBase {
public:
glButton(glBase* parentIn);
void onClick() {
parent->onChildCallback(0, this);
}
};
class glParent : public glBase {
public:
glParent(glBase* parentIn) : parent(parentIn) {
childA = new glSlider(this);
childB = new glButton(this);
}
void onChildCallback(float fIn, void* caller) {
if (caller == childA) {
//slider specific actions
} else if (caller == childB) {
//button specific actions
} else {
//generic actions
}
}
glSlider* childA;
glButton* childB;
};
Besides a reasonably small amount of overhead, the scheme is flexible enough that derived classes can ignore certain components or omit them altogether. I may go back to the function pointer idea later (thanks shahbaz), but half the infrastructure is the same for both schemes anyway and the extra overhead is minimal, especially since the number and variety of controls will be rather small. Having the callback function use a nested response is actually a little better since you don't need a separate function for each child object (eg onUpButton, onDownButton, etc).

Don't understand how this C++ method works, and want to do something similar

I'm trying to add another function to a large program I've been working on. It's a 3D game, and a lot of it was built before I got here. If I want to add something, I'll usually look for other places where something similar has been done and make my changes based off that. In this instance however the method I'm trying to learn from is very complex and I don't really know what is going on (and thus don't know what I need to change about it to make it do what I want it to do).
Here is the normal method:
class Action_GoToZone : public Action {
public:
Action_GoToZone() {}
void eval(const Dialog& dialog, State& state) const {
ZoneParser::getSingleton().load("../media/zones/" + mZoneFilename, false);
GameState::getSingleton()._changeState("GameMode");
}
static Action* Create(const Script2::Parser::List& list) {
Action_GoToZone* action = new Action_GoToZone();
if(list.size() != 1)
throw Translator::TranslateException("GoToZone Action takes exactly one parameter");
const Script2::Parser::ListElement& e1 = list.front();
if(!e1.mIsIdentifier)
throw Translator::TranslateException("GoToZone Action only takes identifiers");
action->mZoneFilename = String(e1.mIdentifier.mString);
action->mReturnFilename = ZoneParser::getSingleton().getLastFilename();
return action;
}
private:
String mZoneFilename;
String mReturnFilename;
};
All I want my method to do is to call a function within a different class. Here is what I attempted:
class Action_SetJob : public Action {
public:
Action_SetJob() {}
void eval(const Dialog& dialog, State& state) const {
GameModeState::changeJob(1); //This is the class/function I want it to call.
}
static Action* Create(const Script2::Parser::List& list) {
Action_SetJob* action = new Action_SetJob();
if(list.size() != 1)
throw Translator::TranslateException("SetJob Action takes exactly one parameter");
const Script2::Parser::ListElement& e1 = list.front();
if(!e1.mIsIdentifier)
throw Translator::TranslateException("SetJob Action only takes identifiers");
action->GameModeState::changeJob(1);
return action;
private:
int changeJob;
}
};
I don't really know what action-> is for... I tried it with taking out action->GameModeState::changeJob(1); and all content below that but that threw up errors.
This probably isn't enough information to solve the problem, but I'd be happy with any explanation about the method, if you can.
If I understand correctly what you are trying to do, then this should accomplish it:
class Action_SetJob : public Action {
public:
Action_SetJob() {}
void eval(const Dialog& dialog, State& state) const {
GameModeState::changeJob(newJob);
}
static Action* Create(const Script2::Parser::List& list) {
Action_SetJob* action = new Action_SetJob();
if(list.size() != 1)
throw Translator::TranslateException("SetJob Action takes exactly one parameter");
const Script2::Parser::ListElement& e1 = list.front();
if(!e1.mIsInteger)
throw Translator::TranslateException("SetJob Action only takes integers");
action->newJob = e1.mInteger.mInt;
return action;
}
private:
int newJob;
};
Obviously since C++ is context-sensitive (it's actually an undecidable language), I cannot know what other members your classes have so I guessed what could be likely.
You want to parse an integer that you can pass to the function you are trying to call when the action gets evaluated.
This is assuming your changeJob method is static. If it is not actually static, you will have to somehow figure out the target object; you can do that by adding an other parameter to your script function for example.
If you want more details, we need more information!
-> is a pointer reference. It looks like your objects are pointers (from the * after the object type). Is the problem with the pointer operations or with something else? From what you wrote, I'm not exactly sure what entirely to offer help with aside from your mention of action->

I need to create a simple callback in c++? Should I use boost::function?

Suppose I have some code like this:
class Visitor {
public:
Visitor(callBackFunction) {}
void visit() {
//do something useful
invokeCallback();
}
}
class ClassThatCanBeVisited {
Visitor &visitor;
public:
ClassThatCanBeVisited(Visitor &_visitor) : visitor(_visitor){}
void someUsefulMethod() {
int data= 42;
visitor.visit(data);
}
};
void callBackFunction() {
//do something useful in the context of the Main file
}
int main() {
Visitor visitor;
ClassThatCanBeVisited foo(visitor);
foo.someUsefulMethod();
}
I need to create a simple callback that will be called whenever the Visitor::visit() is called. I know that I probably should put the code of the callback inside my Visitor, but it is in a different context, so I would like to pass the callBackFunction() to the Visitor so he could invoke my callback function.
I looked for things on the web and saw boost::function, but c++ already has the basic functors.
Which one should I use for better clarity of the code? The callback is going to be a simple void() function, but it might grow, you never know the future :)
What is the recommended way to do this?
Yes boost::function would do this well. That's a very common usage of it. You will need to use boost::bind to bind the instance to the member function.
func = boost::bind( &MyClass::CallbackFunc, this);
Would be how you would do that from within the class.
Be sure the "this" doesn't dissapear or your boost function will crash in the middle of some boost header somewhere.
You can use callback interface and its hierarchy if you don't want to use boost::function.
class VisitorCallback
{
public:
virtual void handle( const Visitor& ) = 0;
};
If you have or can use boost::function - use it, it is a good way to get rid of all those callback classes.
Edit:
#edisongustavo:
boost::function and boost::bind won't probably make your code more readable. But it will give you an opportunity to pass free functions ( I mean functions out of class and static class functions ) as callback as well as existing functions of any class.
With boost functions you can pass functions with for example 2 parameters as callback which expect only one parameter.
typedef boost::function< void ( int ) > IntExpectingCallback;
void TwoIntFunction( int, int );
{
}
...
IntExpectingCallback callback = boost::bind( TwoIntFunction, 5, _1 );
But again, this won't make your code more readable unless all your team knows and favor boost.
The above answers are great, but I'd just like to point out something you mentioned in your question, which is still relevant to your choice between C++ callback objects (in Mykola's answer) and boost.
"the callback is going to be a simple void() function, but it might grow, you never know the future :)"
This is probably the worst reason to extra, unnecessary functionality - that is "just in case you need it". If you don't know - then don't do more than is necessary, chances are your guess will be wrong anyway, especially by the time you need it.
On the other hand, if you do know that it is extremely likely you will need the functionality very soon, then it might be worth adding it.
Again to re-iterate what Mykola said - if you already have boost in your project and your team likes it, then use that, but otherwise it may be overkill.