У меня проблемы со следующим кодом:
#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)
Других решений пока нет …