Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Tricky!

97 views
Skip to first unread message

Bonita Montero

unread,
Jul 29, 2019, 7:49:58 AM7/29/19
to
I need a class-function / method that returns a function-pointer
to the same type of class-function. How do I implement this? I
need this to have a kind of state-machine where each state-func-
tion returns a pointer to the next state function. I.e I would
write: "while( (fn = state->*fn()) != nullptr );". I see no way
to define the type of fn since it is recursive.


Öö Tiib

unread,
Jul 29, 2019, 9:30:17 AM7/29/19
to
Perhaps there are no way to make a function that return function
pointer of its own type. However I do not understand the need
of it. There is state and there is its handler and if you
really need conversions between state and handler then you may
make conversion constructors/operators ... but in my humble
opinion it feels a bit messy and confusing. Here is example:

#include <iostream>

// state
class State
{
public:
using Handler = State (*)(int);

State(Handler h)
:handler_(h)
{ }

operator Handler() {return handler_;}

private:
Handler handler_;
};

// example handlers
State DoSomethingA(int param);

State DoSomethingB(int param);

// example of usage
int main()
{
State::Handler s(DoSomethingA(0));
s = s(1);
s = s(2);
s = s(3);
s = s(4);
}

// implementations of handlers
State DoSomethingA(int param)
{
std::cout << "A: " << param << '\n';
return DoSomethingB;
}

State DoSomethingB(int param)
{
std::cout << "B: " << param << '\n';
return DoSomethingA;
}

If it does miss what you asked for then post actual
example code what are your handlers and what usage
are you trying to achieve.


Alf P. Steinbach

unread,
Jul 29, 2019, 11:59:28 AM7/29/19
to
On 29.07.2019 15:30, Öö Tiib wrote:
> On Monday, 29 July 2019 14:49:58 UTC+3, Bonita Montero wrote:
>> I need a class-function / method that returns a function-pointer
>> to the same type of class-function. How do I implement this? I
>> need this to have a kind of state-machine where each state-func-
>> tion returns a pointer to the next state function. I.e I would
>> write: "while( (fn = state->*fn()) != nullptr );". I see no way
>> to define the type of fn since it is recursive.
>
> Perhaps there are no way to make a function that return function
> pointer of its own type. However I do not understand the need
> of it.

I think she is inspired by (possibly someone else who is inspired by) an
article by the Go language creator.

As I recall his examples work nicely in Go, or assembly language, or a
more dynamic language like Python, but have to be rewritten with some
indirection for a language with strong static type checking like C++.

The reason for doing it that way, in languages where it's simple, is the
textual simplicity of the source code. Since it doesn't give that
textual simplicity in C++, it's not a good way in C++. It's doable, just
not in any practical way.


Cheers!,

- Alf

Sam

unread,
Jul 29, 2019, 8:51:39 PM7/29/19
to
Correct, but you can get pretty close, something like this:



Sam

unread,
Jul 29, 2019, 8:52:11 PM7/29/19
to
Correct, but you can get pretty close, something like this:

#include <iostream>

class state_machine {

public:

struct next_state_ret;

typedef next_state_ret (state_machine::*next_state)();

struct next_state_ret {

next_state_ret (state_machine::*stateptr)()=nullptr;

operator bool() const
{
return stateptr != nullptr;
}
};

inline next_state_ret transition(next_state_ret current_state)
{
return (this->*(current_state.stateptr))();
}

static next_state_ret initial_state()
{
return {&state_machine::initial};
}

next_state_ret initial()
{
std::cout << "Initial state" << std::endl;
return { &state_machine::state1 };
}

next_state_ret state1()
{
std::cout << "State 1" << std::endl;
return { &state_machine::state2 };
}

next_state_ret state2()
{
std::cout << "State 2" << std::endl;
return { nullptr };
}
};

int main()
{
state_machine sm;

auto state=sm.initial_state();

while (state)
{
state=sm.transition(state);
}
return 0;
}

Chris Vine

unread,
Jul 30, 2019, 8:58:26 AM7/30/19
to
Are you after some kind of lazy list (aka streams)? If so I have
stream/node classes with macros and supporting functions (including
stream_take()/stream_for_each() functions which are analogous to your
while block), which I can post: if so do you want the stream also to
memoize or just act lazily?

But you may be after something else.

Tim Rentsch

unread,
Jul 30, 2019, 10:32:11 AM7/30/19
to
Did you not understand the question? Your "solution"
doesn't do anything like what he is asking for.

Tim Rentsch

unread,
Jul 30, 2019, 11:03:39 AM7/30/19
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 29.07.2019 15:30, <<D6 F6 [05b6]>> Tiib wrote:
>
>> On Monday, 29 July 2019 14:49:58 UTC+3, Bonita Montero wrote:
>>
>>> I need a class-function / method that returns a function-pointer
>>> to the same type of class-function. How do I implement this? I
>>> need this to have a kind of state-machine where each state-func-
>>> tion returns a pointer to the next state function. I.e I would
>>> write: "while( (fn = state->*fn()) != nullptr );". I see no way
>>> to define the type of fn since it is recursive.
>>
>> Perhaps there are no way to make a function that return function
>> pointer of its own type. However I do not understand the need
>> of it.
>
> I think she is inspired by (possibly someone else who is inspired
> by) an article by the Go language creator.
>
> As I recall his examples work nicely in Go, or assembly language, or
> a more dynamic language like Python, but have to be rewritten with
> some indirection for a language with strong static type checking
> like C++.

The problem here is not strong static type checking but the lack
of recursive types in C++. A language can have recursive types
and also have strong static type checking.

> The reason for doing it that way, in languages where it's simple, is
> the textual simplicity of the source code. Since it doesn't give
> that textual simplicity in C++, it's not a good way in C++. It's
> doable, just not in any practical way.

That depends on what is meant by "practical". It can be done
like this:

#include <iostream>

class State {
using Nexter = ...;

public:
State(){}
Nexter r0(){ return &State::r1; }
Nexter r1(){ return &State::r2; }
Nexter r2(){ return &State::rn; }
Nexter rn(){ return 0; }
};

void
run_state_machine(){
State *s = new State;

for( auto f = &State::r0; f; f = (s->*f)() ){
::std::cout << "Got one\n";
}
}

with a fairly short (five-ish lines) elaboration for the "...".
Personally I think this approach offers a fairly nice textual
simplicity, and is eminently practical.

If someone thinks five lines of overhead is too much, the "..."
can be made into a template, giving

using Nexter = WrapMemberFunctionPointer< State >;

which provides an even nicer source text.

Rick C. Hodgin

unread,
Jul 30, 2019, 11:17:45 AM7/30/19
to
On 7/30/2019 11:03 AM, Tim Rentsch wrote:
> That depends on what is meant by "practical". It can be done
> like this:
>
> #include <iostream>
>
> class State {
> using Nexter = ...;
>
> public:
> State(){}
> Nexter r0(){ return &State::r1; }
> Nexter r1(){ return &State::r2; }
> Nexter r2(){ return &State::rn; }
> Nexter rn(){ return 0; }
> };
>
> void
> run_state_machine(){
> State *s = new State;
>
> for( auto f = &State::r0; f; f = (s->*f)() ){
> ::std::cout << "Got one\n";
> }
> }


A better solution might be a state machine that can iterate N
times setup at instantiation, and then optionally reset when
exhausted so it can be re-entered the second time (untested,
but generally speaking this concept should work):


#include <iostream>

class State
{
using Nexter = ...;

public:
State(int nStateCount)
{
nState_ = -1;
nStateMax_ = max(1, nStateCount);
}

Nexter next(bool lReset = false)
{
if (++nState < nStateMax)
return &this->next; // Return self

// When we get here, we're done with this state traversal
if (lReset)
nState = -1; // Prepare for the next one

// Indicate this state is exhausted
return null;
}

void reset(int nState = -1)
{
nState_ = max(-1, min(nState, nStateMax));
}

int state(void) { return nState_; }
int max(void) { return nStateMax_; }

private:
int nState_;
int nStateMax_;
};

void run_state_machine()
{
State* s = new State(4);
...

--
Rick C. Hodgin

Alf P. Steinbach

unread,
Jul 30, 2019, 12:00:58 PM7/30/19
to
Short and clear source code and reasonably good efficiency.


> It can be done like this:
>
> #include <iostream>
>
> class State {
> using Nexter = ...;
>
> public:
> State(){}
> Nexter r0(){ return &State::r1; }
> Nexter r1(){ return &State::r2; }
> Nexter r2(){ return &State::rn; }
> Nexter rn(){ return 0; }
> };
>
> void
> run_state_machine(){
> State *s = new State;
>
> for( auto f = &State::r0; f; f = (s->*f)() ){
> ::std::cout << "Got one\n";
> }
> }

Yes, that's mainly the basic technique I had in mind: an extra level of
indirection, the solution to every computer science problem.

Nit-picks: (1) a State instance doesn't actually hold state, yet the
member functions are not `static`, and (2) there's a needless dynamic
allocation and memory leak.

Fixing those issue, it can go like this (in practice one would have some
input argument to each function, so it can decide which state to go to):


class State
{
struct Nexter
{
using Func = auto() -> Nexter;
Func* m_p_func;

operator Func* () const { return m_p_func; }
Nexter( Func* const f ): m_p_func( f ) {}
};

State() = delete;

public:
static auto r0() -> Nexter { return &State::r1; }
static auto r1() -> Nexter { return &State::r2; }
static auto r2() -> Nexter { return &State::rn; }
static auto rn() -> Nexter { return nullptr; }
};

#include <iostream>
using namespace std;

auto main() -> int
{
for( auto f = &State::r0; f; f = f() ) {
cout << "State " << reinterpret_cast<void const*>( f ) <<
"." << endl;
}
}

Here the reinterpret_cast is only conditionally supported by the
standard (since C++11, in order to support Posix), so it's not 100%
portable. I guess that on a Harvard architecture it won't compile. But
then one would have more labor-intensive problems to deal with...


> with a fairly short (five-ish lines) elaboration for the "...".

Not sure what you're thinking of there?


> Personally I think this approach offers a fairly nice textual
> simplicity, and is eminently practical.
>
> If someone thinks five lines of overhead is too much, the "..."
> can be made into a template, giving
>
> using Nexter = WrapMemberFunctionPointer< State >;
>
> which provides an even nicer source text.

Well, to my mind the indirection adds complexity so that even though the
code is short it's not IMO /clear/, and for debugging it's not so clear
which state one is in, just by looking at a function address.

But, subjective opinion. ;-)


Cheers!,

- Alf

Öö Tiib

unread,
Jul 30, 2019, 12:23:03 PM7/30/19
to
On Tuesday, 30 July 2019 17:32:11 UTC+3, Tim Rentsch wrote:
> Tiib <oot...@hot.ee> writes:
>
> > If it does miss what you asked for then post actual
> > example code what are your handlers and what usage
> > are you trying to achieve.
>
> Did you not understand the question? Your "solution"
> doesn't do anything like what he is asking for.

Yes, I tried to express that doubt. Can't you read?
Your habit to answer in useless manner starts to feel
strange. Additionally ... I suspect that Bonita is she.

Tim Rentsch

unread,
Aug 10, 2019, 5:19:14 PM8/10/19
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 30.07.2019 17:03, Tim Rentsch wrote:
>
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>
Not a level of indirection, a layer of abstraction. Those aren't
the same thing. The abstraction here is a five-minute exercise
to write, ignorable in most of the defining class (that's one
value of using an abstraction), completely invisible to client
code, and incurs no run-time cost. So I think it meets the
criteria you gave.

> Nit-picks: (1) a State instance doesn't actually hold state, yet the
> member functions are not `static`, and (2) there's a needless dynamic
> allocation and memory leak.

In cases like this where I am sketching out a solution to someone
else's question, I assume without really thinking about it that
people who read my comments are tracking enough to focus on those
aspects that are relevant to the original problem, and not be
distracted by incidental matters. Apparently that was a bad
assumption here. Taking up your points in reverse order:

(1) Yes the code above does a 'new' but not a 'delete'. That has
no important bearing on the mechanism I was trying to explain.

(2) We don't know that the dynamic allocation is needless,
because we don't know what or how much member data the 'State'
class might have in the context of the OP's question.

(3) The member functions are regular member functions, because
that's what the OP was asking about, and because, based on what
question was asked, it seems obvious that the object in question
is expected to have internal state (aka member data) that is
manipulated by the various 'Nexter' member functions called
within the object.


> Fixing those issue, it can go like this (in practice one would have
> some input argument to each function, so it can decide which state to
> go to):
>
>
> class State
> {
> struct Nexter
> {
> using Func = auto() -> Nexter;
> Func* m_p_func;
>
> operator Func* () const { return m_p_func; }
> Nexter( Func* const f ): m_p_func( f ) {}
> };
>
> State() = delete;
>
> public:
> static auto r0() -> Nexter { return &State::r1; }
> static auto r1() -> Nexter { return &State::r2; }
> static auto r2() -> Nexter { return &State::rn; }
> static auto rn() -> Nexter { return nullptr; }
> };
>
> #include <iostream>
> using namespace std;
>
> auto main() -> int
> {
> for( auto f = &State::r0; f; f = f() ) {
> cout << "State "
> << reinterpret_cast<void const*>( f )
> << "." << endl;
> }
> }
>
> Here the reinterpret_cast is [...]

I skipped over any questions about whether the cast would have
problems since they aren't important to what you're explaining.

The OP included a code fragment that clearly showed calling
member functions through pointer-to-member-function return
values. (This code fragment appears in a quoted portion above.)
Is there some reason you're giving an example that doesn't
conform to that interface?


>> with a fairly short (five-ish lines) elaboration for the "...".
>
> Not sure what you're thinking of there?

Much like yours but using pointer-to-member-function rather than
pointer-to-function, to wit:

using Nexter = struct Hidden {
using PMF = Hidden (State::*)();
Hidden( PMF p0 ) : p( p0 ) {}
operator PMF(){ return p; }
PMF p;
};


>> Personally I think this approach offers a fairly nice textual
>> simplicity, and is eminently practical.
>>
>> If someone thinks five lines of overhead is too much, the "..."
>> can be made into a template, giving
>>
>> using Nexter = WrapMemberFunctionPointer< State >;
>>
>> which provides an even nicer source text.
>
> Well, to my mind the indirection adds complexity so that even though
> the code is short it's not IMO /clear/,

I don't think of what I suggested as an indirection, but as an
abstraction. A principal value of abstraction is to hide complexity
by tucking it away somewhere so it can be ignored afterwards. Here
I think that virtue is achieved rather nicely.

If someone were to think of a scheme along these lines not as an
abstraction but as an indirection, and one which is not meant to
hide inner workings, that could very well be confusing. I don't
know why someone would want to think of this approach that way.

> and for debugging it's not so
> clear which state one is in, just by looking at a function address.

I think how you are conceptualizing the problem is not the same
as how the OP is conceptualizing the problem. From how the
question was asked I inferred that 'State' is not just the
integer state of a finite state machine, but something more
elaborate (and perhaps much more elaborate) that knows what to do
to accomplish state transitions as well as which state should be
"gone to". And there may not be a one-to-one mapping between
'Nexter' member functions and states of the FSM that the 'State'
object is in; that information may not even be available from
just knowing what the pointer value is. If we want to know
something about what state the object is in, presumably we should
ask the object using some other (not yet stated) member function.

> But, subjective opinion. ;-)

I suspect your opinion here is shaped largely by how you are framing
the question. I took the OP at face value that what was being asked
for is in fact what is wanted. It's interesting that in this thread
three different people have suggested solutions to problems other
than what OP was asking about.

Tim Rentsch

unread,
Aug 10, 2019, 5:45:13 PM8/10/19
to
Tiib <oot...@hot.ee> writes:

> On Tuesday, 30 July 2019 17:32:11 UTC+3, Tim Rentsch wrote:
>
>> Tiib <oot...@hot.ee> writes:
>>
>>> If it does miss what you asked for then post actual
>>> example code what are your handlers and what usage
>>> are you trying to achieve.
>>
>> Did you not understand the question? Your "solution"
>> doesn't do anything like what he is asking for.
>
> Yes, I tried to express that doubt. Can't you read?

I read fine. My question was just a question, not an accusation.
I asked because I was curious to know if your confusion about not
understanding the question had progressed beyond merely being
uncertain.

> Your habit to answer in useless manner starts to feel
> strange.

I'm sure other people feel the same way about your answers.

> Additionally ... I suspect that Bonita is she.

I don't remember seeing any postings where OP makes an explicit
statement about his or her gender. If and when I do, I expect
what phrasings I use in the future will change to reflect the new
information.

Bonita Montero

unread,
Aug 11, 2019, 3:06:42 AM8/11/19
to
> But you may be after something else.

Yes.

Öö Tiib

unread,
Aug 11, 2019, 6:23:16 AM8/11/19
to
On Sunday, 11 August 2019 00:45:13 UTC+3, Tim Rentsch wrote:
> Tiib <oot...@hot.ee> writes:
>
> > On Tuesday, 30 July 2019 17:32:11 UTC+3, Tim Rentsch wrote:
> >
> >> Tiib <oot...@hot.ee> writes:
> >>
> >>> If it does miss what you asked for then post actual
> >>> example code what are your handlers and what usage
> >>> are you trying to achieve.
> >>
> >> Did you not understand the question? Your "solution"
> >> doesn't do anything like what he is asking for.
> >
> > Yes, I tried to express that doubt. Can't you read?
>
> I read fine. My question was just a question, not an accusation.
> I asked because I was curious to know if your confusion about not
> understanding the question had progressed beyond merely being
> uncertain.

To where uncertainty about understanding of a problem can progress?
Ignorance about any and all things is default and dominant state
of all minds. So the only progress from there possible seems to
be towards (often vague, often incorrect,) understandings of some
aspects of few things. Did you mean some other "progress"?

My current understanding is that states are some kind of "modes
of being" between what can be "transitions". My reading of
OP request was that the "states-and-transitions" have to be
implemented as "state-functions". I expressed that it
feels uncommon. Alf wrote that the goal of it is in textual
simplicity. Plausible. The code (even if terse) would not still
look neither like a state diagram nor like any form of transition
table. So I lost interest in the thread.

> > Your habit to answer in useless manner starts to feel
> > strange.
>
> I'm sure other people feel the same way about your answers.

My ideas may feel to be useless to many but at least I try
to provide some. I meant that your lack of attempt to express
any thoughts started to feel strange. Have I offended you
somehow?

Tim Rentsch

unread,
Aug 18, 2019, 1:02:30 AM8/18/19
to
Tiib <oot...@hot.ee> writes:

> On Sunday, 11 August 2019 00:45:13 UTC+3, Tim Rentsch wrote:
>
>> Tiib <oot...@hot.ee> writes:
>>
>>> On Tuesday, 30 July 2019 17:32:11 UTC+3, Tim Rentsch wrote:
>>>
>>>> Tiib <oot...@hot.ee> writes:
>>>>
>>>>> If it does miss what you asked for then post actual
>>>>> example code what are your handlers and what usage
>>>>> are you trying to achieve.
>>>>
>>>> Did you not understand the question? Your "solution"
>>>> doesn't do anything like what he is asking for.
>>>
>>> Yes, I tried to express that doubt. Can't you read?
>>
>> I read fine. My question was just a question, not an accusation.
>> I asked because I was curious to know if your confusion about not
>> understanding the question had progressed beyond merely being
>> uncertain.
>
> To where uncertainty about understanding of a problem can progress?
> Ignorance about any and all things is default and dominant state
> of all minds. So the only progress from there possible seems to
> be towards (often vague, often incorrect,) understandings of some
> aspects of few things. Did you mean some other "progress"?

I'm sorry about how my statement was phrased. It made sense in
my head when I wrote it but now I think it might be not so good.
If you don't mind maybe we can just drop it and leave it at that.

>>> Your habit to answer in useless manner starts to feel
>>> strange.
>>
>> I'm sure other people feel the same way about your answers.
>
> My ideas may feel to be useless to many but at least I try
> to provide some. I meant that your lack of attempt to express
> any thoughts started to feel strange. Have I offended you
> somehow?

I have the sense that your communication style is more
argumentative than constructive. I don't like arguing, and I
don't like trying to have a productive conversation with people
who are more interested in argument than communication. So in
exchanges with you I've learned not to say very much, because
trying to say more would for me be counter-productive.

Öö Tiib

unread,
Aug 18, 2019, 2:53:13 AM8/18/19
to
On Sunday, 18 August 2019 08:02:30 UTC+3, Tim Rentsch wrote:
> Tiib <oot...@hot.ee> writes:
>
> > On Sunday, 11 August 2019 00:45:13 UTC+3, Tim Rentsch wrote:
> >
> >> Tiib <oot...@hot.ee> writes:
> >>
> >>> On Tuesday, 30 July 2019 17:32:11 UTC+3, Tim Rentsch wrote:
> >>>
> >>>> Tiib <oot...@hot.ee> writes:
> >>>>
> >>>>> If it does miss what you asked for then post actual
> >>>>> example code what are your handlers and what usage
> >>>>> are you trying to achieve.
> >>>>
> >>>> Did you not understand the question? Your "solution"
> >>>> doesn't do anything like what he is asking for.
> >>>
> >>> Yes, I tried to express that doubt. Can't you read?
> >>
> >> I read fine. My question was just a question, not an accusation.
> >> I asked because I was curious to know if your confusion about not
> >> understanding the question had progressed beyond merely being
> >> uncertain.
> >
> > To where uncertainty about understanding of a problem can progress?
> > Ignorance about any and all things is default and dominant state
> > of all minds. So the only progress from there possible seems to
> > be towards (often vague, often incorrect,) understandings of some
> > aspects of few things. Did you mean some other "progress"?
>
> I'm sorry about how my statement was phrased. It made sense in
> my head when I wrote it but now I think it might be not so good.
> If you don't mind maybe we can just drop it and leave it at that.

Fine, I have also not much to add to it.

>
> >>> Your habit to answer in useless manner starts to feel
> >>> strange.
> >>
> >> I'm sure other people feel the same way about your answers.
> >
> > My ideas may feel to be useless to many but at least I try
> > to provide some. I meant that your lack of attempt to express
> > any thoughts started to feel strange. Have I offended you
> > somehow?
>
> I have the sense that your communication style is more
> argumentative than constructive. I don't like arguing, and I
> don't like trying to have a productive conversation with people
> who are more interested in argument than communication. So in
> exchanges with you I've learned not to say very much, because
> trying to say more would for me be counter-productive.

I have dropped viewing discussions as some kind of combat long
ago. Some things remain controversial and subjects of viewpoint,
style or taste. Participating in discussions has still point for
me when I have some arguments to add, to question or to
clarify. How else can a discussion be productive?

Tim Rentsch

unread,
Aug 18, 2019, 8:23:05 AM8/18/19
to
Tiib <oot...@hot.ee> writes:

> On Sunday, 18 August 2019 08:02:30 UTC+3, Tim Rentsch wrote:
>
>> Tiib <oot...@hot.ee> writes:
[...]
>>> My ideas may feel to be useless to many but at least I try
>>> to provide some. I meant that your lack of attempt to express
>>> any thoughts started to feel strange. Have I offended you
>>> somehow?
>>
>> I have the sense that your communication style is more
>> argumentative than constructive. I don't like arguing, and I
>> don't like trying to have a productive conversation with people
>> who are more interested in argument than communication. So in
>> exchanges with you I've learned not to say very much, because
>> trying to say more would for me be counter-productive.
>
> I have dropped viewing discussions as some kind of combat long
> ago. [...]

I didn't say combative, I said argumentative. They aren't the
same thing.
0 new messages