为函数定义一个typedef,该函数返回一个函数指针,指向像它自己这样的函数

时间:2013-11-10 16:27:50

标签: c++ c pointers

我对这个有点难过。考虑它的最简单方法是实现状态机状态并返回下一个状态的一组函数(请注意 - 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;
}

2 个答案:

答案 0 :(得分:2)

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

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的抽象基类来执行此操作。

答案 1 :(得分:1)

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