Polymorphic Callback Implementation - c++

I am using Component Based Architecture in my application. I'm at the stage where I need to allow a Component to specify a callback that will be executed upon an event.
typedef void(Component::*EventCallback) ();
typedef std::pair<Component*, EventCallback> EventDelegate;
The problem with the above type definition is that all components inherit from Component but will never be a direct Component. So the following line of code is not valid:
MoveComponent* mc = new MoveComponent(); // inherits from Component
EventDelegate ed(mc , &MoveComponent::moveToXY); // Compiler error here: expects Component* not MoveComponent*, and same for EventCallback.
Any ideas how I can achieve a 'Polymorphic' callback? Or any other design/implementation advice?
Example usage:
typedef void(Component::*EventCallback) ();
typedef std::pair<Component*, EventCallback> EventDelegate;
class Component {
// ...
};
class MoveComponent : public Component {
public:
MoveComponent() {
EventDelegate ed(this, &MoveComponent::moveToXY);
ComponentManager::registerEvent(ed);
}
void moveToXY() { }
};
class ComponentManager {
public:
static void registerEvent(EventDelegate ed) {
evtRegistry.push_back(ed);
}
static void runEvent(EventDelegate ed) {
for (int i=0; i<evtRegistry.size(); i++) {
Component* context = evtRegistry.at(i).first;
EventCallback ec = evtRegistry.at(i).second;
context->*ec();
}
}
private:
static std::vector <EventDelegate> evtRegistry;
};

using EventDeligate = std::function<void()>;
auto cp = std::make_shared<MoveComponent>();
auto ed = EventDeligate([cp](){ cp.moveToXY(); });
To do it your way, Component must have a (possibly pure) virtual function moveToXY.

Related

How to create an interface to allow for the construction of different nested derived classes in C++?

My goal is to construct a derived classes nested class from the interface. However the nested classes don't have the same constructors. The question is how can I make an interface to create two different "sub-nested" classes.
Constraints:
Cannot use Heap
Nested Classes' Methods cannot be called before it is constructed
C++ 17
ITest::INestedTest* MakeTest(ITest* test, ITest::Config config)
{
// Can't call directly because it's not on the interface i.e. test.InitializeNestedTest ...
// Only workable situation is this:
if (condition)
{
auto myTest = static_cast<Test2::Test*>(test);
int p = 2;
return myTest->InitalizeNestedTest(config, p);
// ERROR function returning abstract class not allowed
} else {
auto myTest = static_cast<Test1::Test*>(test);
return myTest->InitalizeNestedTest(config);
// ERROR function returning abstract class not allowed
}
}
This static cast didn't return what I wanted previously because I was returning a pointer to a locally defined variable, which was pointed out in the comments. How am I able to return a class from this since it's an abstract class, do i need to cast it again or make multiple functions?
Test1::Test myTest;
auto myNestedTest = myTest.InitializeNestedTest(config);
I've thought of a few options but none of them seem right, or I'm not entirely sure how to implement them
Have an overloaded Virtual function for each type on the interface and then override them on the subclass (not sure if possible and doesn't seem like the right way to do it)
Extend the Config struct Test2 namespace so that it includes parameter p, so that they all have the same prototype and put it on the interface. (is it possible to "extend" the struct" from the interface?)
Maybe use a different type of cast, or do so in a different way?
I've included the definitions of my Interface and two subclasses for reference.
class ITest
{
//other things in ITest.hpp not relevant to question
public:
struct Config
{
int a;
bool enable;
};
class INestedTest
{
public:
virtual void Enable() const = 0;
virtual void Configure(Config const& config)
{
if(config.enable)
{
Enable();
}
}
};
};
namespace Test1
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
NestedTest(Config const& config)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config)
{
return NestedTest(config);
}
};
};
namespace Test2
{
class Test : public ITest
{
public:
class NestedTest : public ITest::INestedTest
{
public:
using Parameter = int;
NestedTest(ITest::Config const& config, Parameter p)
{
Configure(config);
}
void Enable() const override
{
//impl
}
}; // End NestedTest
NestedTest InitalizeNestedTest(Config const& config, NestedTest::Parameter p)
{
return NestedTest(config, p);
}
};
};
Maybe you could make the object static so it's declared in RAM at compile time (and not heap or stack).

How would you design a function that attaches children of a Component class to an Object class if the components can hold different data?

In my program, I have an Object class to which we can attach components that all derive from a base Component class. Since a component can have data that are initialized through it's constructor, when we call Object::addComponent() we need to pass the data for this particular component
#include <vector>
class Component;
class Object
{
public:
Object() {}
/* The challenge comes from implementing this function, the signature will change later in this post
and ideally it would return the added component */
void addComponent();
private:
std::vector<Component*> m_components;
};
class Component
{
public:
Component(Object* owner) : m_owner(owner) {}
// Note the pure virtual destructor, meaning Component is meant to be derived
virtual ~Component() = 0;
private:
Object* m_owner;
};
Here are two Component derived classes for our example
// This component holds an int
class ComponentDerivedA : public Component
{
public:
ComponentDerivedA(Object* owner, int data) : Component(owner), m_data(data) {}
virtual ~ComponentDerivedA() override {}
private:
int m_data;
};
// This component holds a string
class ComponentDerivedB : public Component
{
public:
ComponentDerivedB(Object* owner, char* message) : Component(owner), m_message(message) {}
virtual ~ComponentDerivedB() override {}
private:
char* message;
};
The only solution I came for to implement the addComponent() function the way I want to is to create an enum and a struct:
enum class ComponentType { A, B };
struct ComponentInfo
{
ComponentType type;
int data;
char* message
};
So we change the signature for Object::addComponent() to the following
void* Object::addComponent(const ComponentInfo& info);
And here is a possible implementation
void* Object::addComponent(const ComponentInfo& info)
{
switch(info.type)
{
case A:
{
// We ignore cleaning up for this example but it would go in the destructor
ComponentDerivedA* a = new ComponentDerivedA(this, info.data);
m_components.push_back(a);
return a;
}
break;
case B:
{
// We ignore cleaning up for this example but it would go in the destructor
ComponentDerivedB* b = new ComponentDerivedB(this, info.message);
m_components.push_back(b);
return b;
}
break;
}
}
And here is how we would use it
int main()
{
Object obj;
ComponentInfo info{0};
info.type = ComponentType::A;
info.data = 5;
obj.addComponent(info);
/*
If I wanted to use the component right after I would have to do:
reinterpret_cast<ComponentDerivedA>(obj.addComponent(info)).doSomething();
*/
return 0;
}
This solution works okay but anytime you want to call addComponent() you have to declare a struct before, the only benefit is if you add multiple components you can reuse the same struct and just change the data between each call, also is if you add a new component type you have to expand the enum and the function, if you have many component the switch can become very large but the code inside it remains pretty repetitive and simple. And the final flaw is that it's up to the caller to cast the return value as the component type.
Here is a possible solution.
Note the use of std::unique_ptr instead of regular c-pointers.
#include <memory>
#include <vector>
struct Component{};
class Object {
public:
Object() {}
template <typename TDerivedComponent, typename... TArgs>
TDerivedComponent * addComponent(TArgs&&... args){
auto ptr = std::make_unique<TDerivedComponent>
(std::forward<TArgs>(args)...);
TDerivedComponent * result = ptr.get();
m_components.push_back(std::move(ptr));
return result;
}
private:
std::vector<std::unique_ptr<Component> > m_components;
};
struct ComponentA : public Component {
ComponentA(int x, int y){}
};
struct ComponentB : public Component {};
struct Invalid{};
int main(){
Object obj;
ComponentA * a = obj.addComponent<ComponentA>(1, 2);
ComponentB * b = obj.addComponent<ComponentB>();
// obj.addComponent<Invalid>(); -> error!
}
You actually can store a derived object into a baseclass object pointer which u already have declared as in the vector.
To make your derived objects also call the correct methods you have to declare the method as virtual inside the base class.
your addComponent() function can then take the pointer of the baseClass
addComponent(Component * c)
with that signature it can also take derived object pointers.
You should read about static vs dynamic binding in C++.

How to add functionality from combination of different derived class?

I have multiple handlers derived from base Handler class which can do single data updates individually.
For eg.
class Handler {
public:
Data_t dbdata_;
public:
virtual void updateFlags() = 0;
}
class AHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; }
}
class BHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagB = 1; }
}
class CHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagC = 1; }
}
Individual handlers are called based on input flags in request. If request contains multiple flags, then in this case I want to try to avoid creating additional 6 handlers individually like following.
class ACHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; dbdata_.flagC = 1; }
}
class ABCHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; dbdata_.flagB = 1; dbdata_.flagC = 1 }
}
Main function code will be something similar to this.
void process(Request_t *request)
{
Handler *handler;
if (request->flagA)
handler = new AHandler();
else if (request->flagB)
handler = new BHandler();
....
...
handler->updateFlags();
}
Is there a better way to approach this problem, by re-writing how the handlers are connected to each other ?
Thanks in advance.
If this is all your classes do, then I dont think u need any other class then Handler. Just simply let the Handler handle all the flags. It will be easy and simple like that. I think you might be overthinking this. Get a working simple version and then review it and decide if u need to and can refractor it.
I dont know what type your Request_t->flag(x) and Data_t->flag(x) is.
But cant you just do
dbdata_.flagA = request_t.flagA;
dbdata_.flagB = request_t.flagB;
etc. If you can maybe make them an array instead of individual variables, for easier setting.
You may want to consider a policy-based class design. For this, we define both a variadic function template, execute(), and a class template, HandlerHolder, that inherits from Handler and overrides the updateFlags() member function:
template<typename FlagUpdater, typename... FlagUpdaters>
void execute(Data_t& data) {
execute<FlagUpdater>(data);
if constexpr (sizeof...(FlagUpdaters))
execute<FlagUpdaters...>(data);
}
template<typename... FlagUpdaters>
class HandlerHolder final: public Handler {
public:
void updateFlags() override {
if constexpr (sizeof...(FlagUpdaters))
execute<FlagUpdaters...>(dbdata_);
}
};
To this variadic class template, HandlerHolder, you can pass classes (i.e., policies) as template arguments that are callables and set the proper flags. The function call operator (i.e., operator()) of these policy classes are called in its overridden member function updateFlags().
You would then define the policy classes like:
struct AFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagA = 1;
}
};
struct BFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagB = 1;
}
};
struct CFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagC = 1;
}
};
Note that you can also easily define policies for clearing the flags, for example:
struct CFlagClearer {
void operator()(Data_t& dbdata) const {
dbdata.flagC = 0;
}
};
By means of type aliases you can introduce type names for the handlers you were looking for:
using ACHandler = HandlerHolder<AFlagSetter, BFlagSetter>;
using ABCHandler = HandlerHolder<AFlagSetter, BFlagSetter, CFlagSetter>;

Calling the method of class with unidentified type

I have a class named MyClass that is subscribed by another class. When some events happen, MyClass should notify subscribers.
I'm trying to use template for the subscriber's type. Because I don't want to let others(who are in charge of subscriber class) need to care about modifying MyClass for subscribing.
So I've written codes below,
class MyClass {
public:
template<typename T>
void subscribeEvents(const T &controller)
{
m_subscriber = static_cast<T*>(m_subscriber);
m_subscriber = &controller;
}
void notifyPositionChanged(const long &position) const {
(m_subscriber)->onPositionChanged(position);
}
private:
void m_subscriber; // will be changed to array or something else
}
Actually the controller object has a method namedonPositionChanged.
But as you know, it's not compiled for this line.
(m_subscriber)->onPositionChanged(position);
Now I understand why it's an error, but the problem is that I don't know how to modify codes or change my design. Please let me know what I'm missing and misunderstanding. Thanks in advance.
You dont need to use template for this. Just use a base class for your subscribers. And MyClass operate on your base class
class ISubscribe {
public:
virtual void onPositionChanged(const long &position) = 0;
};
class MyClass {
public:
void subscribeEvents(ISubscribe *controller)
{
m_subscriber = controller;
}
void notifyPositionChanged(const long &position) const {
(m_subscriber)->onPositionChanged(position);
}
private:
ISubscribe *m_subscriber; // will be changed to array or something else
};
class SampleSubscriber : public ISubscribe {
public :
void onPositionChanged(const long &position) override{
...
}
};
void main() {
SampleSubscriber s;
MyClass m;
m.subscribeEvents(&s);
....
}
You need to define a common interface to all your subscribers, then use this interface as m_subscriber's type. Savagely casting whatever parameter you receive to a defined type will lead only to undefined behaviors.
Use std::function:
class MyClass {
public:
template<typename CALLBACK>
void subscribeEvents(CALLBACK &&controller)
{
m_subscriber = std::forward<CALLBACK>(controller);
}
void notifyPositionChanged(const long &position) const
{
if (m_subscriber)
m_subscriber(position);
}
private:
std::function<void(const long&)> m_subscriber;
}
This gives the subscriber full freedom of what it wants to subscribe. For example:
there.subscribeEvents([this](const long &pos) { handlePosChange(pos); }

What is the best way to dynamically check the types of a class that uses variadic inheritance?

I am writing an entity component system for a 2D game engine that uses variadic templates to construct game objects. Here is the object class which is just the container for all components. I removed the unrelated stuff.
template<class ... Components>
class Object : public Components...{
public:
Object(Game* game) : Components(game)...{
}
};
The components are inherited by the object but I am trying to find the best way to check the type of these components so that they can correctly communicate with each other. For example, the Physics component would contain the updated position of the object. The Drawable component needs to get that position so it can be drawn in the correct spot in the world. I would like to add an update function to Object that updates each component and transfers whatever information can/needs to be transferred between present components.
polymorphism is what you want .
Simply make all components like that :
public Object
{
enum TYPE{
COMPONENT,,
GAMEOBJECT,
ETC,,,
};
Object(TYPE id){m_id = id;}
protected:
TYPE m_id;
virtual void Update(void) = 0;
virtual void Render(void) = 0;
public:
void GetTypeOf(void)const{return m_id;}
};
class Component : Object
{
enum COMPONENT_TYPE
{
COLLIDER,
RENDERER,
ETC,,,,
};
Component() : Object (COMPONENT){/**/}
virtual void Update(void){return;}
virtual void Render(void){return;}
};
class BoxCollider : Component
{
BoxCollider(void) : Component(BOXCOLLIDER){/**/}
void Update(void)
{
//to do
}
void Render(void)
{
//to do
}
};
then you can simply have a data structure of Object* or Component*
and you can iterate through that way :
std::vector<Component*>::iterator components = ComponentVector.begin();
for(;components != ComponentVector.end() ; ++components)
{
*(component)->Update();
*(component)->Render();
std::cout << "id" << *component->getTypeOf() << std::endl;
}
The Object class inherits from all its Components, that means that actually it is all its components.
You can use this information to design your update method.
As an example:
#include <cassert>
struct Game { };
struct Physics {
int position{0};
Physics(Game *) { }
void update(void *) { }
};
struct Drawable {
Drawable(Game *) { }
void update(Physics *physics) {
physics->position = 42;
}
};
template<class ... Components>
class Object: public Components... {
public:
Object(Game* game) : Components(game)... { }
void update() {
int a[] = { (Components::update(this), 0)... };
}
};
int main() {
Game game;
Object<Physics, Drawable> object{&game};
assert(object.position == 0);
object.update();
assert(object.position == 42);
}
Here you can see as Drawable receives Physics when its update method is called.
The drawbacks of this solution are:
The update methods of the components must get a pointer argument even if they do not need to refer to any other component.
If there exists a component that needs to refer to more than one component, you have either to get two or more pointers as arguments of the update method or to cast a void * around.