为函数定义 typedef,该函数返回指向类似自身的函数的函数指针

Defining a typedef for a function that returns a function pointer to a function like itself

本文关键字:函数 指针 typedef 定义 返回      更新时间:2023-10-16

我对这个有点困惑。 最简单的思考方法是一组实现状态机状态并返回下一个状态的函数(请注意 - FSM 示例只是激励性的,我不是在寻找如何设计 FSM)。

所以我正在寻找一个 C 样式的 typedef 和一个 C++ 11,使用 StateHandler(一个函数指针)的定义,其中代码类似于(忽略声明等):

// typdef for StateHandler
// -- and to see the new c++ 11 way --
// using StateHandler = StateHandler (*)(State *, int);  // note -- does not compile
StateHandler StateOne(State *state, int arbitraryArgs) {
    // do stuff and go to state 2
    return StateTwo;
}
StateHandler StateTwo(State *state, int arbitraryArgs) {
     // do stuff and go to state 1
    return StateOne;
}

你不能这样做,因为它需要无限类型。您需要在此处使用函数对象。

struct StateOne;
struct StateTwo;
struct StateOne {
    StateTwo operator()(State* state, int arbitraryArgs) const;
};
struct StateTwo {
    StateOne operator()(State* state, int arbitraryArgs) const;
};
StateTwo StateOne::operator()(State* state, int arbitraryArgs) const {
    // do stuff
    return StateTwo();
}
StateOne StateTwo::operator()(State* state, int arbitraryArgs) const {
    // do stuff
    return StateOne();
}

如果需要可以存储这些函数对象之一的变量,则需要类型擦除。您可以使用包含纯虚拟operator()函数的抽象基类和std::unique_ptr .

其中 FuncType 是函数类型的名称,您不能让它返回FuncType 。 但是你可以让它在函数类型(StateHandler)周围返回一个轻量级包装器。 然后我们可以定义函数调用运算符operator(),使其行为类似于函数。

struct StateHandler;
typedef StateHandler (*FuncType)(State *, int); //using FuncType = StateHandler (*)(State *, int);
struct StateHandler {
        FuncType m_f;
        StateHandler(FuncType f_) : m_f(f_) {}
        StateHandler operator() (State *s, int arbitraryArgs) {
                return m_f(s,arbitraryArgs);
        }
};
// declare both functions in advance, so their definitions can return each other
StateHandler StateOne(State *state, int arbitraryArgs);
StateHandler StateTwo(State *state, int arbitraryArgs);
StateHandler StateOne(State *state, int arbitraryArgs) {
    // do stuff and go to state 2
    return StateTwo;
}
StateHandler StateTwo(State *state, int arbitraryArgs) {
     // do stuff and go to state 1
    return StateTwo;
}