首页 文章

C循环类依赖tinyfsm - 前向声明不起作用

提问于
浏览
0

我遇到以下代码时遇到问题:

#include "tinyfsm.hpp"

struct Event : tinyfsm::Event { };

struct State1;
struct State2;

struct Fsm : tinyfsm::Fsm<Fsm> {
    virtual void react(Event const &) { }
    virtual void entry() { }
    void exit() { };
    virtual ~Fsm() { }
};

struct State1 : Fsm{
    void react(Event const & event) override { transit<State2>(); }
    void entry() override { }

};

struct State2 : Fsm{
    void react(Event const & event) override { transit<State1>(); }
    void entry() override { }
};

FSM_INITIAL_STATE(Fsm, State1)

编译器给出了以下消息:

"..\src\tinyfsm.hpp", line 134: cc0513:  error: a value of type "State2 *" cannot be assigned to an entity of type "Fsm *"
current_state_ptr = &_state_instance<S>::value;
                      ^
      detected during instantiation of "void tinyfsm::Fsm<F>::transit<S>() [with F=Fsm, S=State2]" at line 31 of "..\src\testbed.cpp"

我很确定这是因为编译器不理解State2是从Fsm继承的 .

有没有办法打破循环依赖,或给编译器相关的信息,以便它能正确编译?

我正在使用ccblkfn.exe版本8.12.0.0(在blackfin处理器上工作)

我认为它可能是一个编译器错误,因为这个代码在g 6.3.0上编译得很好 .

1 回答

  • 0

    编译错误似乎是因为:

    struct Fsm : tinyfsm::Fsm<Fsm>
    

    这在全局命名空间中声明 struct 名为 Fsm .

    标头定义了 tinyfsm 命名空间中具有相同名称的类型 . 宏调用

    FSM_INITIAL_STATE(Fsm, State1)
    

    扩展到此宏声明:

    #define FSM_INITIAL_STATE(_FSM, _STATE)                               \
    namespace tinyfsm {                                                   \
      template<> void Fsm< _FSM >::set_initial_state(void) {              \
        current_state_ptr = &_state_instance< _STATE >::value;            \
      }                                                                   \
    }
    

    最终扩展到:

    namespace tinyfsm {
      template<> void Fsm<Fsm>::set_initial_state(void) {
        current_state_ptr = &_state_instance< _STATE >::value;
      }
    }
    

    您认为 <Fsm> 部分最终会引用什么?不是你的类,而是tinyfsm命名空间中的 Fsm 模板 . 接连发生了 .

    有几种简单的方法可以解决这种歧义 .

    FSM_INITIAL_STATE(::Fsm, State1)
    

    宏现在在全局命名空间中插入对 Fsm 结构的引用 .

    另一种方法是简单地将 Fsm 类重命名为其他类 .

    第三种方法是将所有类放入它们自己的命名空间,然后(在命名空间之外) .

    namespace fsmimpl {
    
    // Your existing class declarations
    
    }
    
    FSM_INITIAL_STATE(fsmimpl::Fsm, State1)
    

相关问题