Самый простой способ запомнить это посмотреть на std::numeric_limits< int >::max()
Например ( из MSDN ),
// numeric_limits_max.cpp
#include
#include
using namespace std;
int main() {
cout << "The maximum value for type float is: "
<< numeric_limits::max( )
<< endl;
cout << "The maximum value for type double is: "
<< numeric_limits::max( )
<< endl;
cout << "The maximum value for type int is: "
<< numeric_limits::max( )
<< endl;
cout << "The maximum value for type short int is: "
<< numeric_limits::max( )
<< endl;
}
Это возможно, но это плохая идея. Блоки итераторов были созданы, чтобы помочь вам писать собственные итераторы для коллекций, а не для решения универсальной проблемы реализации конечных автоматов.
Если вы хотите написать конечный автомат, просто напишите конечный автомат. Это не трудно. Если вы хотите написать много конечных автоматов, напишите библиотеку полезных вспомогательных методов, которые позволят вам четко представлять конечные автоматы, а затем используйте свою библиотеку. Но не злоупотребляйте языковой конструкцией, предназначенной для чего-то совершенно другого, которое просто использует конечные автоматы в качестве детали реализации. Это затрудняет чтение, понимание, отладку, поддержку и расширение кода вашего конечного автомата.
(И, кстати, я дважды ошибся, когда прочитал ваше имя. Одного из разработчиков C # также зовут Мэтт Уоррен!)
Да, это абсолютно возможно и легко сделать. Вы можете наслаждаться использованием конструкций потока управления ( для
, foreach
, while
, ... goto
(используя goto
] особенно подходит для этого сценария;))) вместе с yield
s для его создания.
IEnumerator<State> StateMachine
(Func<int> currentInput /* gets current input from IO port */,
Func<int> currentOutput) {
for (;;) {
if ((currentInput() & 1) == 0)
yield return new State("Ready");
else {
if (...) {
yield return new State("Expecting more data");
SendOutput(currentOutput());
while ((currentInput() & 2) != 0) // while device busy
yield return new State("Busy");
else if (...) { ... }
}
}
}
// consumer:
int data;
var fsm = StateMachine(ReadFromIOPort, () => data);
// ...
while (fsm.Current != "Expecting more data")
fsm.MoveNext();
data = 100;
fsm.MoveNext();
Блоки итераторов действительно реализуют конечные автоматы, но хитрый бит получает следующий ввод. Как вы узнаете, куда двигаться дальше? Я предполагаю, что у вас могла бы быть какая-то общая переменная «текущего перехода», но это несколько неприятно.
Если вам не нужен какой-либо ввод (например, ваш конечный автомат просто циклически переключается между состояниями), тогда это просто, но это не интересный вид :)
Вы можете описать интересующий вас тип конечного автомата?
Хотя это не конечный автомат в классическом смысле, статья о Micro Threading на основе итераторов творчески использует yield для действий на основе состояний.
IEnumerable Patrol ()
{
while (alive){
if (CanSeeTarget ()) {
yield return Attack ();
} else if (InReloadStation){
Signal signal = AnimateReload ();
yield return signal;
} else {
MoveTowardsNextWayPoint ();
yield return TimeSpan.FromSeconds (1);
};
}
yield break;
}