这是我要编写的代码的简化版本:
template<typename Derived>
class StateMachine
{
public:
void SetState(Derived::State s) {
static_cast<Derived*>(this)->TransitionTo(s);
}
};
class MyFSM : public StateMachine<MyFSM>
{
public:
enum class State {
State1,
State2,
State3
};
void TransitionTo(State s) {
_state = s;
}
private:
State _state = State::State1;
};
我正在clang中使用c++ 11。我在这里得到的错误是
10:17: error: missing 'typename' prior to dependent type name 'Derived::State'
的声明的SetState
。我也尝试过添加typename Derived::State DerivedState;
,然后使用DerivedState
而不是Derived::State
,但是后来我得到error: unknown type name 'DerivedState'
。更令人困惑的是,我尝试了
typedef typename Derived::State DerivedState;
,然后收到错误消息:error: no type named 'State' in 'MyFSM'
。我的最后一次尝试是typedef enum class Derived::State DerivedState;
,然后我得到了最令人困惑的错误:error: no enum named 'State' in 'MyFSM'
。我对这里的模板不感兴趣,欢迎您对此有所帮助!另外,这里可能会有更好的模式。我要做的主要事情是
StateMachine
类具有一些通用功能,然后有许多不同的状态机,每个状态机都有自己的状态和转换功能。我有另一种方法,需要将this
传递给SetState
(当从MyFSM
中调用时,这是我正在做的简化版本),但这是丑陋的,这是由于其自身的原因。我很想避免这种受诱惑的类,但是我的主要目标是使派生类尽可能容易编写和理解。 最佳答案
您可以通过将SetState
用作模板来延迟类型推断:
#include <type_traits>
template<typename Derived>
class StateMachine
{
public:
template <typename State>
void SetState(State s) {
static_assert(std::is_same<State, typename Derived::State>::value, "Not a derived state");
static_cast<Derived*>(this)->TransitionTo(s);
}
};
class MyFSM : public StateMachine<MyFSM>
{
public:
enum class State {
State1,
State2,
State3
};
void TransitionTo(State s) {
_state = s;
}
private:
State _state = State::State1;
};
int main() {
MyFSM fsm;
fsm.SetState(MyFSM::State::State1);
// error: static assertion failed: Not a derived state
// fsm.SetState(0);
}