c++templatesc++14template-meta-programmingenable-if

Adding optional argument to variadiac class template (C++14)


In our C++14 code base our modules have two types of extensions. Imagine group A as a run-at-start-up type, and type B as run-at-shut-down. The module is simply handed a list of all extension and executes them according to their group. The module distinguishes automatically in which group they are: group A has a runAtStartUp function and group B has a runAtShutDownfunction. This check is done via template check at compile time. (If an extension had both functions, it would be run both at start-up and at shut-down, but right now no such extension exists).

One of our extensions is currently always run at shut-down. It is a variadic class template looking like this:

template <typename... Ts>
class myExtension{
...
void runAtShutDown();
}

We got the request to make it possible to run it at start-up instead, without changing the default behavior.

In order to be able to run it at start-up, we need to remove the runAtStartUp function and add the runAtShutDown function. I know how I can do that via a std::enable_if check if I have a condition at compile time. I can add a bool flag to the template argument list that would indicate which mode I want to use:

template <bool mode, typename... Ts>
class myExtension{

  template <bool enabled=mode>
  std::enable_if<enabled, void>
  runAtStartUp();

  template <bool enabled=mode>
  std::enable_if<!enabled, void>
  runAtShutDown();

}

However, I would have to add this flag to all instances where this class is used. This would require a lot of changes to modules that want to keep using the old default behaviour. I am looking for a way to only require changes when the new, non-default behaviour is to be used.

Inheriting from the existing class does not seem like the solution as I also need to remove the existing runAtShutDown function, not just add the runAtStartUp. If it is possible to do that I do now know how.

The best solution I came up with so far is to create a base class which has neither runAt... function and two inheriting classes that add only the required runAt... function. I have not tried this yet, so I'm not 100% that this actually works.

I am NOT a template metaprogramming expert, so it is possible that some of my assumptions are wrong.

Is there a good (better?) way to indicate which mode the extension should be used in and add/remove the required function?


Solution

  • A class to transform any "shutDown extension" to "startUp extension" seems to do the job, something like:

    template <typename Extension>
    struct toStartUp
    {
        void runAtStartUp() { extension.runAtShutDown(); }
    
        Extension extension;
    };