I'm trying to create a Finite State Machine hierarchy type structure. What I'm trying to do is check to see if the current state exist if it doesn't return, then check to see if all of the next states exist. As soon as one of them fails it will return as well.
I'm not sure if it can be done using fold expressions or variadic parameter pack expansion or not, but I've been getting errors for parameter pack not being expanded. I'm not sure if I can do it this way or if I would need a helper function or some other mechanism.
Here is my approach:
template<unsigned N>
class FSM {
public:
std::vector<State<N>> states;
// ... other parts of class
template<typename Current, typename... NextStates>
void addStateTransition(Current* currentState, NextStates*... nextStates) {
// look to see if the current state is a state in our container.
auto current = std::find(states.begin(), states.end(), currentState);
if (current == states_.end()) {
std::cout << "Could not find " << currentState->id_ << " in this State Machine.";
return;
}
// Able to use fold expressions or not to check if all of the next states are in our container?
auto next = std::find(states.begin(), states.end(), nextStates);
// ? I've tried the ellipsis inside, outside and on both sides of the ending parenthesis, and none of them work.
if (next == states.end()) {
std::cout << "Could not find " << nextStates->id_ << " in this State Machine.";
return;
}
// if all of nextStates... are found, do something else here
}
};
To use a fold-expression, you need something you can fold over. You need some expression for each element in the parameter pack. The expression you need is complicated: a call to std::find
, checking the result, etc. So it's best to stick that in a lambda:
auto lookup = [&](auto nextState) {
// one single find
auto it = std::find(states.begin(), states.end(), nextState);
if (it == states.end()) {
std::cout << "Could not find " << nextState->id_ << " in this State Machine.";
return false;
}
return true;
};
// fold over that
bool const allFound = (lookup(nextStates) && ...);
allFound
will be true
if all the states are found, or false
if at least one is missing... in which case something will be logged. This handles empty packs too... if nextStates...
is empty, allFound
is trivially true
.