samedi 17 août 2019

Given both types, can I determine if a virtual function have been overridden?

I am designing a system that is built from a collection of modules. The base Module class has a set of virtual functions that do nothing by default, but can be overridden in derived module classes if they are needed.

For example, one of these functions is OnUpdate(). Currently when an update occurs, I loop through all modules and run this function on each of them. Of course, this results in many "wasted" calls on any module that does not override the relevant function.

Given that most modules do not override most member functions (and profiling indicates that this is a bottleneck in my system), what I'd prefer to do is keep track of which modules DO override a member function and execute only those. At the moment, I am planning to keep an extra vector of only those module pointers that need to be run.

My problem is that collecting this information requires me to detect whether or not a module has overridden each member function. I can do this analysis on module creation when I know the exact derived type that I'm working with, so I think it should be possible, but the test that I expected to work does not.

Here's some simplified detection code that fails:

    template <typename T>
    T & AddModule() {
      static_assert(std::is_base_of<Module, T>,
                    "AddModule() can only take module types.");

      // Create the new module and store it.
      auto mod_ptr = std::make_shared<T>();
      modules.push_back(mod_ptr);

      // If the module has OnUpdate() track it!
      // *** This test is not working! ***
      if (&T::OnUpdate != &Module::OnUpdate) {
        on_update_mods.push_back(mod_ptr);
      }

      // ...lots more tests here...

      return *mod_ptr;
    }

Is there some other way that I can handle this detection?

I'm also happy to hear alternate ideas for how to achieve my goal. I definitely want to keep it easy for module writers to simply implement any of the designated functions and have them called as appropriate.

The only other option I've come up with so far is to NOT have the virtual functions in the Module base class and then use SFINAE to detect them in the derived class, followed by wrapping them in lambdas and storing a vector of functors to run. I think that will work BUT it will be slightly slower (more indirection with the functors) and more error prone (right now if you make a typo in a member function name the override keyword will throw an error...)

Thanks in advance for any other suggestions.





Aucun commentaire:

Enregistrer un commentaire