I have a templated function hierarchy which works like this:
template <typename T>
SomeClass<T> Primary(SomeInputClass& input) {
vector<SomeClass<T>> individual_results;
for (auto& next_states : input.GetNextStates()) {
//
// change input's internal state here, then call:
//
if (/* needs recursion based on some condition in input */ )
individual_results.push_back(SwitcherCaller<T>(input));
else
// some base case operations with individual_results
}
SomeClass<T> aggregated_results = AggregateIndividualResults<T>(individual_results);
return aggregated_results;
}
template <typename T>
SomeClass<T> SwitcherCaller(SomeInputClass& input) {
string type = input.GetTypeFromInternalState();
if (type == "ClassA") return Switcher<T, ClassA>(input);
else if (type == "ClassB") return Switcher<T, ClassB>(input);
else if (type == "ClassC") return Switcher<T, ClassC>(input);
}
template <typename T, typename C>
SomeClass<T> Switcher(SomeInputClas& input) {
SomeClass<C> child_results = Primary<C>(input);
SomeClass<T> parent_results = CreateParentResultsFromChild<T, C>(input, child_results);
return parent_results;
}
The above code captures what I want to do generically in a data processing pipeline. This pipeline is generic, so it can be called with different kinds of templates by different callers.
The callers need to do the following:
- Make the first call to Primary with a root template, with an instance of SomeInputClass with its internal state configured as required.
- Implement SwitcherCaller for all possible child classes that can be reached as defined by the internal states.
For example, assume there are two callers. Caller 1 does the following:
void PrimaryCallerOne() {
SomeInputClass input = CreateInputForCallerOne();
SomeClass<RootClassOne> results = Primary<RootClassOne>(input);
}
template <typename T>
SomeClass<T> SwitcherCaller(SomeInputClass& input) {
string type = input.GetTypeFromInternalState();
if (type == "ClassOneA") return Switcher<T, ClassOneA>(input);
else if (type == "ClassOneB") return Switcher<T, ClassOneB>(input);
else if (type == "ClassOneC") return Switcher<T, ClassOneC>(input);
}
And Caller 2 does this:
void PrimaryCallerTwo() {
SomeInputClass input = CreateInputForCallerTwo();
SomeClass<RootClassTwo> results = Primary<RootClassTwo>(input);
}
template <typename T>
SomeClass<T> SwitcherCaller(SomeInputClass& input) {
string type = input.GetTypeFromInternalState();
if (type == "ClassTwoA") return Switcher<T, ClassTwoA>(input);
else if (type == "ClassTwoB") return Switcher<T, ClassTwoB>(input);
}
Calling Primary is easy. My problem is, how do I design this to implement SwitcherCaller() elegantly? One way is to put all these functions in a class, make SwitcherCaller() virtual, and have each caller implement it.
Is there any other way without classes? Maybe using functors?
Aucun commentaire:
Enregistrer un commentaire