Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c++ Subject: Re: "C++20 Coroutines" by Martin Bond Date: Wed, 06 Oct 2021 13:19:12 -0700 Organization: A noiseless patient Spider Lines: 46 Message-ID: <865yu9rjnj.fsf@linuxsc.com> References: <87zgs1yby6.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="f63a7b6827eb8960d7c84af554cfeab9"; logging-data="917"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/zKjbHuZQC4ec2BNxa/K0jqU6O+Jrf7d8=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:+KA21rrc98V0zAv7siygJVAd288= sha1:B1WqEGrq3J/LyyUlKu7pTAuOH9k= Xref: csiph.com comp.lang.c++:81883 Ben Bacarisse writes: > Bonita Montero writes: > >> State-machines are _always_ spahgetti-code (while( !end ) >> switch( state ) { ... }), even when you write them conventionally. > > Obviously one person's spaghetti is another person's farfalle, but > in my opinion, if the state is a (a pointer to a) function that > returns (a pointer to) the next state, then you just get a clean > loop calling a function: > > data d = { ... }; > State state = initial; > while (state) state = (State)state(&d); > > C++ has trouble writing the recursive type, so you need a cast, but > its a safe cast. In C++, needing a cast can be avoided by wrapping the function pointer in a class or struct, as for example: class State { typedef State (*Go)( data & ); Go go; public: State( Go g ) : go( g ) {} operator bool(){ return go; } State operator()( data &data ){ return go( data ); } }; void run_state_machine( State initial, data &data ){ State s = initial; while( s ) s = s( data ); } The example above is specific to a partcular type of "data" being acted on, but it's easy to generalize around that shortcoming by using templates.