首页 > 解决方案 > 带有 tinyfsm 的 C++ 循环类依赖 - 前向声明不起作用

问题描述

我在使用以下代码时遇到问题:

#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 上编译得很好。

标签: c++circular-referenceblackfin

解决方案


编译错误似乎是因为:

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>部分最终指的是什么?不是你的类,而是Fsmtinyfsm 命名空间中的模板。希拉里随之而来。

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

FSM_INITIAL_STATE(::Fsm, State1)

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

另一种方法是简单地将您的Fsm类重命名为其他名称。

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

namespace fsmimpl {

// Your existing class declarations

}

FSM_INITIAL_STATE(fsmimpl::Fsm, State1)

推荐阅读