c++ - 带有 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 上编译得很好。
解决方案
编译错误似乎是因为:
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>
部分最终指的是什么?不是你的类,而是Fsm
tinyfsm 命名空间中的模板。希拉里随之而来。
有几种简单的方法可以解决这种歧义。
FSM_INITIAL_STATE(::Fsm, State1)
Fsm
宏现在在全局命名空间中插入对您的结构的引用。
另一种方法是简单地将您的Fsm
类重命名为其他名称。
第三种方法是将所有类放入它们自己的命名空间中,然后(在命名空间之外)。
namespace fsmimpl {
// Your existing class declarations
}
FSM_INITIAL_STATE(fsmimpl::Fsm, State1)