2016-02-28 3 views
0

Я пытаюсь написать очень минимальный конечный автомат в C++. Я бы хотел, чтобы состояния были методами класса машины, и каждое состояние при запуске должно возвращать новое состояние для перехода. Естественно, я использую несколько typedef, чтобы помочь.Тип функции, которая возвращает себя

template <typename C, typename E> 
using State = State<C, E> (C::*)(Stream<E>&); 

Состояние должно быть функцию-член класса (в C), который принимает объект потока и дает новое состояние. Я получаю следующую ошибку.

fsm.hpp:8:15: error: ‘State’ does not name a type 
using State = State<C, E> (C::*)(Stream<E>&); 

Очевидно, что State пока не объявлена ​​на линии, которая должна объявить State. Насколько я знаю, нет способа «переслать объявление» typedef, так что это подходящий способ объявить это имя?

+0

'State' соответствует только функции (ну, метод) типа. Сам государственный автомат является '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '. Мне не нужны отдельные экземпляры классов для каждого состояния; Мне просто нужны функции. –

+0

Чтобы уточнить, я хочу, чтобы 'State ' был методом, который принимает аргумент, а затем возвращает новое 'State ', которое само является методом, а не экземпляром класса. –

+0

Понятно, я неправильно понял ваш код. –

ответ

2

Я не уверен, если я могу объяснить, почему то, что вы пытались не работать - я не знаю, если using заявления может быть самоссылающимися, может быть, они не являются.

Но, конечно, в шаблоне класса имя класса, которое в настоящее время определено, вводится в область видимости класса, поэтому вы можете сделать это таким образом.

В этой версии я создаю тип класса, который является тонкой оболочкой над указателем на функцию-член. Я считаю, что оптимизатор должен в основном устранить эту оболочку, но он позволяет вам делать то, что вы хотите, пользуясь введенным именем класса.

Это компилирует и работает в GCC 5.2.0

template <typename T> 
struct Stream {}; 

template <typename C, typename E> 
class State { 
    typedef State (C::*func_t)(Stream<E>&); 

    func_t f_; 

public: 
    State(func_t _f) : f_(_f) {} 

    State operator()(C & c, Stream<E> & s) const { 
    return (c.*f_)(s); 
    } 
}; 





struct Foo { 
    State<Foo, int> state_one(Stream<int> &) { return &Foo::state_two; } 
    State<Foo, int> state_two(Stream<int> &) { return &Foo::state_one; } 
}; 

int main() { 
    Foo f; 
    Stream<int> s; 
    f.state_one(s); 
} 
+0

Это более или менее то, что я закончил делать. Один из ответов в дублирующем вопросе был схож с этим. –

Смежные вопросы