折叠表达式,参数包扩展,类成员函数中的递归

时间:2019-08-20 04:53:37

标签: c++ recursion c++17 variadic fold-expression

我正在尝试创建有限状态机层次结构类型结构。我想做的是检查当前状态是否不返回,然后检查是否所有下一个状态都存在。一旦其中之一发生故障,它也会返回。

我不确定是否可以使用折叠表达式或可变参数包扩展来完成它,但是我一直在错误地发现参数包没有被扩展。我不确定是否可以这样做,或者是否需要辅助功能或其他机制。

这是我的方法:

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
    }
};

1 个答案:

答案 0 :(得分:1)

要使用fold-expression,您需要可以折叠的东西。您需要为参数包中的每个元素提供一些表达式。您需要的表达式很复杂:调用bool board::tryActivateCell(const int x, const int y, const int playerValue) { // Maybe do a check to avoid an overflow if x or y is equal or greater than boardSize const int& boardValue = board[y][x]; if (boardValue != 0 && boardValue != playerValue) { // The other player already activate the cell return false; } // Activate the cell with the value of the current player boardValue = playerValue; return true; } ,检查结果等。因此最好将其放在lambda中:

std::find
如果找到所有状态,则

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,如果至少缺少一个状态,则为true。在这种情况下,将记录某些内容。这也可以处理空包...如果false为空,则nextStates...只是allFound