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 runAtShutDown
function. 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?
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;
};