Let's consider the following example:
(Function<FunctionType>
is just a class that applies some function specified by the enum FunctionType
)
template<FunctionType funcType>
class System {
public:
void doEverything() {
//Iterate through every module in sequence and call doSomething()
}
void undoEverything() {
//Iterate through every module in sequence and call undoSomething()
}
template<class Derived>
void add(GenericModule<Derived>& module) {
//Add module to list
}
};
template<class Derived>
class GenericModule {
private:
Derived* crtp = static_cast<Derived*>(this);
public:
void doSomething() {
crtp->doSomething();
}
void undoSomething() {
crtp->undoSomething();
}
};
template<FunctionType funcType, int param>
class ModuleA : public GenericModule<ModuleA<funcType, param>> {
private:
Function<funcType> func;
public:
void doSomething() {
std::cout << param+1 << "\n";
}
void undoSomething() {
std::cout << func.doFunction(param) << "\n";
}
};
template<FunctionType funcType, int param1, int param2>
class ModuleB : public GenericModule<ModuleB<funcType, param1, param2>> {
private:
Function<funcType> func;
public:
void doSomething() {
std::cout << param1 + param2 << "\n";
}
void undoSomething() {
std::cout << func.doFunction(param1+param2) << "\n";
}
};
int main() {
System<FUNC1> system;
ModuleA<FUNC1, 1> m1;
ModuleB<FUNC1, 1, 2> m2;
system.add(m1);
system.add(m2);
system.doEverything();
system.undoEverything();
}
Goal: The goal with this is to create multiple modules which together make up a "system" so that with only one call to doEverything()
or undoEverything()
all their respective functions can be executed in sequence. Important is that all modules of a system share the same FunctionType
argument specified in the system
template. I intentionally used CRTP as this has to be highly efficient and thus any use of virtual functions is discouraged.
My approach was to use CRTP to create a common interface GenericModule
from which all modules can be called. I thought the observer pattern might be suitable to register any module in system
.
Problems:
-
How can I implement the add/register functionality in
system
? I'm thinking about a heterogeneous container that stores any type ofGenericModule
or something similar. It's important that this technique has as little overhead as possible which is certainly going to be difficult to implement. I'd also consider a complete re-design of this functionality as this might not be optimal. -
The
FunctionType
argument is only relevant to theSystem
class and not to a particular module. The module still needs this argument for it's functionality and due to efficiency reasons it has to be defined as a template argument so it can be used in a constexpr context. But because this argument is already set in theSystem
class and all it's modules share the same value it's highly redundant for it to be redefined on every instantation of a module. I want to instantiate each module in the context of it's system so that theFunctionType
argument doesn't have to be redefined every single time. In combination with that I't might even be possible thatSystem
automatically adds/registers the module when it's instantiated in it's context.
I have no clue how I could implement all these afromentioned things and that's why I'm asking you.
Update: I just had an idea on how I could solve the first problem. Instead of storing each module in the System
class I could just put a reference to the next module as a member variable in the previous module. But I have not yet figured out how I could set it's type at compile time.
Aucun commentaire:
Enregistrer un commentaire