0

I'm trying to build a entity component system. Here is what I have :

An entity, that can have components : these are derived from a base "Component" class to carry common methods like OnCreated(), etc... Now, I want to add "Systems" that can operate on components to do the actual calculations. For example, a "Physics" system would loop over all physics component to update them, a "Renderer" system would loop over mesh components, etc...

My first idea was to have an template Update method, taking a system as a template type. Then, any component that want to be used by some system would only need to override that specific Update method for that system. Here was the idea :

// base component class
class Component {
    template<class S>
    virtual void Update(float _deltaTime) { } // empty on base component
}

// system class (inherits from the system base class)
class Physics : System {
    void Update(float _deltaTime) {
        // call Update<Physics>(float _deltaTime) on every concerned component
    }
}

// component class somewhat related to the physics system
class Collider : Component {
    void Update<Physics>(float _deltaTime) { /* calculations */ }
}

Now, I've read from here that it is not possible to override template methods. As I'm still learning C++, I can't think of a system that would allow what I want. So is there any smarter / possible ways to do what I want to achieve ?

Thanks in advance :

  • "_Now, I've read from here that it is not possible to override virtual methods_": Of course you can override `virtual` member functions, what would be the point otherwise? But what you can't have are `virtual` member function _templates_ (at all). – user17732522 Jun 18 '22 at 22:32
  • @user17732522 Yes, sorry for the typo ! Edited it out. – LucioleMaléfique Jun 18 '22 at 22:33
  • How do you intend to call `Update`? Show some example and it will be much easier to help you. Doing that might also show whether there are any flaws in your general approach. – user17732522 Jun 18 '22 at 22:34
  • It's quite hard to suggest alternative, because we don't see the bigger picture of what you want to achieve and especially we don't see why there are templates in the first place. Maybe `Update` would have only a few different template arguments, so you could turn `Component` into `PhysicsComponent` and `SomeOtherComponent` and inherit from those. Maybe `Physics` should implement CRTP pattern. Maybe you should look into ducktyping and instead of relying on polymorphism, expect that provided class has methods you need. There are many ways around, each with strengths and weaknesses. – Yksisarvinen Jun 18 '22 at 22:43
  • @Yksisarvinen, I'm trying to make a ecs library, where then the user can creates it's own components and system. When I wrote it at first, my components had Update, Render... methods. But I realized I could be less specific, and let the user explicit these methods if needed. This is were I wanted one update method per System, and to me this was only possible through templates. But I look into the different things you told ! – LucioleMaléfique Jun 19 '22 at 08:11
  • I've tried not to be specific about my issue, but I'll give more detail as asked. First of, @user17732522, Update will be called every frame by the "main ecs manager" who will then call update on every system. – LucioleMaléfique Jun 19 '22 at 08:11
  • @LucioleMaléfique The question is mainly where the template parameter `template` comes into play. From the code you have shown so far, you could just remove it and everything would be fine. – user17732522 Jun 19 '22 at 08:13
  • @user17732522 I want the update method to be specific to a system. For example, a network physics collider will have two updates ; one for the network system, and one for the physics system, which will each be called when the said system will update it. The template is here to differentiate them, so that the user can overload only the update for the system that is interested in the component. – LucioleMaléfique Jun 19 '22 at 08:20
  • @LucioleMaléfique And the caller doesn't statically know which type the `Component` actually is? I think then the only solution to implement it directly is to use `virtual` functions of different names (e.g. `UpdateNetwork`, `UpdatePhysics`) and declare them all as members of `Component` first. But if the `Component` isn't actually overriding one of these and the corresponding `Update*` is called, what should happen then? Simply nothing? – user17732522 Jun 19 '22 at 08:26
  • @user17732522 Yes, if the component does not implement it, the system interpret it as "I am not concerned by this type of component" and skip it. I thought about update for every system, but that means that every time I add a system, I need to add the corresponding update in the base component. And as I'm trying to build this into a library, where then the user can write custom systems, it wouldn't work ! – LucioleMaléfique Jun 19 '22 at 08:51
  • The virtual dispatch mechanism requires that the base class knows about all virtual functions that could be called. So that will not work. Alternatively you could map component types to some e.g. integer values via constants, pass the constant corresponding to the system you want to update as a parameter to a single `Update` and then have the overridden `Update` choose how to act by `switch`ing on that value, possibly forwarding to base class implementations of `Update` if you need that functionality. – user17732522 Jun 19 '22 at 08:56
  • @user17732522 That could be an idea ! However, it requires that every component have a update with a switch in it, which makes the coding quite heavy, and way less easy to use for a generic library – LucioleMaléfique Jun 19 '22 at 09:08
  • @LucioleMaléfique No, it only requires that _if_ a component has a `Update` that it call the base class `Update` (without dynamic dispatch) in the `default` branch. – user17732522 Jun 19 '22 at 09:12

0 Answers0