C++ 递归函数类型



Rob Pike 在 2011 年(链接(发表了关于 Go 中的词法分析器的演讲,他定义了一个这样的类型:

// stateFn represents the state of the scanner
// as a function that returns the next state.
type stateFn func() stateFn

我想在C++中实现相同的目标,但不知道如何:

// 01: error C3861: 'statefn_t': identifier not found
typedef std::function<statefn_t()> statefn_t;
// 02: error C2371: 'statefn_t': redefinition; different basic types
typedef std::function<class statefn_t()> statefn_t;
// 03: error C2371: 'statefn_t': redefinition; different basic types
typedef std::function<struct statefn_t()> statefn_t;
// 04: error C2065: 'statefn_t': undeclared identifier
typedef std::function<statefn_t*()> statefn_t;
// 05: error C2371: 'statefn_t': redefinition; different basic types
typedef std::function<class statefn_t*()> statefn_t;
// 06: error C2371: 'statefn_t': redefinition; different basic types
typedef std::function<struct statefn_t*()> statefn_t;

注意:这个问题可能是相关的(在 Rust 中是一样的(

编辑:

这是我想要实现的目标:

// statefn_t definition goes here ...
statefn_t* func1()
{
    return &func2;
}
statefn_t* func2()
{
    return &func1;
}

类型别名不能是递归的。

要实现状态机(如 go 讲座中使用的状态机(,您需要定义一个自定义类型:

class state
{
public:
    using fn = std::function<state()>;
    state() {}
    state(fn f) : f(f){}
    operator bool() { return (bool)f; }
    operator fn () { return f; }
private:
    fn f;
};

用法:

state::fn stateEnd()
{
    std::cout << "endn";
    return {};
}
state::fn stateTransit()
{
    std::cout << "transitn";
    return stateEnd;
}
state::fn stateStart()
{
    std::cout << "startn";
    return stateTransit;
}

int main() {
    state::fn s = stateStart;
    while(s = s());
}

替代形式:

class state
{
public:
    state() {}
    template<class T>
    state(T&& t) : f(std::forward<T>(t)){}
    operator bool() { return (bool)f; }
    state operator()() { return f(); }
private:
    std::function<state()> f;
};

用法:

state stateEnd()
{
    std::cout << "endn";
    return {};
}
state stateTransit()
{
    std::cout << "transitn";
    return stateEnd;
}
state stateStart()
{
    std::cout << "startn";
    return stateTransit;
}

int main() {
    state s {stateStart};
    while(s = s());
}

正如 Clearer 所评论的那样,下面是一个 C++ 类型stateFn的示例,它的行为类似于函数并递归返回相同类型的实例。

struct stateFn
{
    stateFn& operator() ();
}

如果您希望在运行时解析递归,同时使其尽可能与原始代码相似,则可以使用 boost::any 或 C++17 std::any,如下所示:

std::any end(){ std::cout << "endn"; return {}; }
std::any state(){ std::cout << "some staten"; return &end; }
std::any begin(){ std::cout << "beginn"; return &state; }
void advance( std::any& state )
    { state = std::any_cast<std::any(*)()>(state)(); }
int main()
{
    for( auto state = begin(); state.has_value(); advance( state ) );
}

如果必须在编译时解析递归,则可以利用自动类型推断:

auto end(){ std::cout << "endn"; }
auto state(){ std::cout << "some staten"; return &end; }
auto begin(){ std::cout << "beginn"; return &state; }
int main()
{
    begin()()();
}

当然,这在循环中不起作用,您需要某种编译时迭代方案才能使其有用......

这不是

在C++中做事的自然方式。

在C++中,它更像是混淆,这反映在很难为状态推进函数找到好的自我描述名称,这些函数也是状态:

struct Context {};
class State
{
    using F = auto( Context const& ) -> State;
    F* next_state_;
public:
    auto is_finished() const -> bool { return next_state_ == nullptr; }
    auto operator()( Context const& ctx ) const
        -> State
    { return next_state_( ctx ); }
    State( F* f ): next_state_{ f } {}
    inline State();
};
auto intermediate( Context const& ) { return State{ nullptr }; }
auto start( Context const& ) { return State{ intermediate }; }
State::State(): next_state_{ start } {}
#include <iostream>
using namespace std;
auto main() -> int
{
    State       state;
    Context     ctx;
    cout << boolalpha;
    for( ;; )
    {
        cout << state.is_finished() << endl;
        if( state.is_finished() ) { break; }
        state = state( ctx );
    }
}

最新更新