Topic: state for dynamic objects as language feature


Author: Walt <wkaras@yahoo.com>
Date: Wed, 1 Apr 2009 18:36:38 CST
Raw View
On Mar 31, 6:48 pm, brang...@cix.co.uk (Dave Harris) wrote:
> wka...@yahoo.com (W Karas) wrote (abridged):
>
> > Virtual functions could have multiple definitions, for different
> > object states.
>
> This sounds a bit like the feature Predicate Classes, found in, for
> example, the language Cecil. See for example:
>
> http://web.archive.org/web/20020112001033/www.cs.washington.edu/resea...
> projects/cecil/www/Papers/predicate-classes.html
>
>      By associating methods with predicate classes, method lookup
>      can depend not only on the dynamic class of an argument but
>      also on its dynamic value or state.
>
> As others have said, I don't think it offers enough bang for buck to be
> added to C++.

I'm not able to read the postscipt document, but what you're
describing sounds more like signatures to me:

http://docs.freebsd.org/info/gcc/gcc.info.C++_Signatures.html

What I'm suggesting is less powerful but much easier to implement.



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Thomas J. Gritzan" <phygon_antispam@gmx.de>
Date: Thu, 2 Apr 2009 10:31:28 CST
Raw View
W Karas schrieb:
> (Previously posted in comp.lang.c++)
>
> Virtual functions could have multiple definitions, for different
> object states.
>
> The prototype of a virtual member function could have an optional
> reserve word "for" followed by a comma-separated list of state names.
>
> The statement:
>
> virtual using <state>;
>
> (executed in a member function of the object) would put the object in
> the state named <state>.

All this can easily be done using the... state pattern:

http://en.wikipedia.org/wiki/State_pattern

The problems with your proposal as core language feature:

1) It's difficult to integrate into the other language features. Think
of stateful vtables in the context of multiple inheritance for example.

Then, it'ld have to be thread-safe (in C++0x). What if one thread
changes state while another calls member functions?

With the state pattern, you could ignore the thread-safety stuff if you
know your app is single-threaded, or use a mutex or atomic pointer
exchange if needed.

2) You have one class with many concerns, which is bad OO design.
 While using the state pattern, you have one class responsible for each
state.

--
Thomas

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Walt <wkaras@yahoo.com>
Date: Fri, 3 Apr 2009 10:55:03 CST
Raw View
On Apr 2, 12:31 pm, "Thomas J. Gritzan" <phygon_antis...@gmx.de>
wrote:
> W Karas schrieb:
>
> > (Previously posted in comp.lang.c++)
>
> > Virtual functions could have multiple definitions, for different
> > object states.
>
> > The prototype of a virtual member function could have an optional
> > reserve word "for" followed by a comma-separated list of state names.
>
> > The statement:
>
> > virtual using <state>;
>
> > (executed in a member function of the object) would put the object in
> > the state named <state>.
>
> All this can easily be done using the... state pattern:
>
> http://en.wikipedia.org/wiki/State_pattern

a += 1 could easily be written as a = a + 1 .  When considering how
much repetitive coding a feature will save, one must take the product
of how much work is typically saved by using the feature, and multiply
that by a crude estimate of how frequently the feature will be used.

I would say the fact that this pattern is widely recognized supports
the desirability of a language feature helping to support it.

>
> The problems with your proposal as core language feature:
>
> 1) It's difficult to integrate into the other language features. Think
> of stateful vtables in the context of multiple inheritance for example.

It's complex but it think it's manageable.  States defined by a class
would be assigned a zero base index.  To change state, the index of
the new state would be looked up in an array of vtables accessed using
a pointer in the vtable for the current state.  Disambiguation of
state names using class:: prefixes would be necessary in some cases.

>
> Then, it'ld have to be thread-safe (in C++0x). What if one thread
> changes state while another calls member functions?
>
> With the state pattern, you could ignore the thread-safety stuff if you
> know your app is single-threaded, or use a mutex or atomic pointer
> exchange if needed.

I think the same reasoning applies to the case where the language
supports object state.

>
> 2) You have one class with many concerns, which is bad OO design.
>  While using the state pattern, you have one class responsible for each
> state.

I don't think C++ will ever be the favorite language of those who
think that capabilities should be left out of  language to try to
force people to write better code.  Object state used poorly could be
yet another toy of those who create bloated objects.  But it could
also help avoid repeatatively creating many classes with largely
similar concerns.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: W Karas <wkaras@yahoo.com>
Date: Wed, 25 Mar 2009 18:28:22 CST
Raw View
(Previously posted in comp.lang.c++)

Virtual functions could have multiple definitions, for different
object states.

The prototype of a virtual member function could have an optional
reserve word "for" followed by a comma-separated list of state names.

The statement:

virtual using <state>;

(executed in a member function of the object) would put the object in
the state named <state>.  The statement:

virtual using 0;

would put the object back in the default state.  The boolean
expression:

virtual <virt-mem-fun> using <state>

would return true if, at the point of execution of the expression, a
call to the virtual member function <virt-mem-fun> would execute the
definition of the function valid for state <state> .

I think this feature would have many uses.  For example, if the read
member function was called for a closed file, this could trigger a
version of read that would throw an exception.

A feasible implementation would be to have multiple v-tables, one
appropriate for each state.  State changes would involve changing the
v-pointer(s).  This would get complex with in large inheritance
trees.  The function to change the v-pointer would itself have to be a
hidden virtual function.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Vaclav Haisman <v.haisman@sh.cvut.cz>
Date: Thu, 26 Mar 2009 23:10:41 CST
Raw View
W Karas wrote, On 26.3.2009 1:28:
>[...]
This is something that can be done entirely using the current language as it
is. What you propose is just syntactic sugar and I do not see any pressing
need for it anywhere. In fact, I think that the usefulness of this feature is
very limited.

--
VH

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Walt <wkaras@yahoo.com>
Date: Sat, 28 Mar 2009 12:45:41 CST
Raw View
On Mar 27, 1:10 am, Vaclav Haisman <v.hais...@sh.cvut.cz> wrote:
> W Karas wrote, On 26.3.2009 1:28:>[...]
>
> This is something that can be done entirely using the current language as it
> is.

Well, of course there are many features of C++ that "can be done
entirely" using the features of C.  Run time polymorphism is an
example, it can be done with explicit vtables and vpointers.

One way to get the effect of what I propose is with a 'state' data
member and switch statements in member functions, something like:

int X::x(char a, double b)
   {
     switch (this->state)
       {
       case S1:  return(`this->x_S1(a, b));
       case S2: case S3:  return(this->x_S2_S3(a, b));
       ...
       }
   }

instead of (assuming S2 is the default state):

virtual int X::x(char a, double b) for S1 { ... }

virtual int X::x(char a, double b) for default, S3 { ... }

(A small change here from the OP, using the reserve word 'default' for
the default state instead of the numeral 0.  For convenience and
backwards-compatibility, a member function with no 'for' clause has
the same definition in all states.)

So yes, this feature would have to be useful fairly often for it to be
worth it.  Conceptually, one can see reasons that it might be used
frequently.  For example, in a simulation of some human social group
or organization that covered many decades of time.  The behavior of a
particular "human" object could change drastically depending on
whether the human being represented was a baby, young child, teenager,
young adult, etc.  You could maybe try to do this using multiple
classes with a common base class, like:

human_p = teenager_p = new Teenager(child_p);
delete child_p;

But somehow anything along these lines seems like it would inevitably
be fairly icky.

'for' clauses could maybe also be used after the 'private' and
'protected' keywords, to specify members that could only be access in
a particular state.  Perhaps the nominal initialization point for data
members only accessible in a particular state would be the first time
the state was entered.

> What you propose is just syntactic sugar and I do not see any pressing
> need for it anywhere. In fact, I think that the usefulness of this feature is
> very limited.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Vaclav Haisman <v.haisman@sh.cvut.cz>
Date: Sun, 29 Mar 2009 15:52:12 CST
Raw View
Walt wrote, On 28.3.2009 19:45:
> On Mar 27, 1:10 am, Vaclav Haisman <v.hais...@sh.cvut.cz> wrote:
>> W Karas wrote, On 26.3.2009 1:28:>[...]
>>
>> This is something that can be done entirely using the current language
>> as it is.
>
> Well, of course there are many features of C++ that "can be done entirely"
>  using the features of C.  Run time polymorphism is an example, it can be
>  done with explicit vtables and vpointers.
>
> One way to get the effect of what I propose is with a 'state' data member
>  and switch statements in member functions, something like:
>
> int X::x(char a, double b) { switch (this->state) { case S1:
> return(`this->x_S1(a, b)); case S2: case S3:  return(this->x_S2_S3(a, b));
>  ... } }
>
> instead of (assuming S2 is the default state):
>
> virtual int X::x(char a, double b) for S1 { ... }
>
> virtual int X::x(char a, double b) for default, S3 { ... }
You do not need even need switch to do that, you can use lookup table of
your
own. All you need is a table of structures with member function pointers.

struct X
{
struct MyVMT
{
   int (X::* foo)(char, double);
};

enum State
{
   S1, S2
};

State state;
static MyVMT const vmt[2];

int foo(char c, double d)
{
   return (this->*vmt[state].foo) (c, d);
}

private:
int foo_S1 (char, double);
int foo_S2 (char, double);
};

X::MyVMT const X::vmt[2] = { { &X::foo_S1 }, { &X::foo_S2 } };

>
> (A small change here from the OP, using the reserve word 'default' for the
>  default state instead of the numeral 0.  For convenience and
> backwards-compatibility, a member function with no 'for' clause has the
> same definition in all states.)
>
> So yes, this feature would have to be useful fairly often for it to be
> worth it.  Conceptually, one can see reasons that it might be used
> frequently.  For example, in a simulation of some human social group or
> organization that covered many decades of time.  The behavior of a
> particular "human" object could change drastically depending on whether
> the human being represented was a baby, young child, teenager, young
> adult, etc.  You could maybe try to do this using multiple classes with a
>  common base class, like:
>
> human_p = teenager_p = new Teenager(child_p); delete child_p;
>
> But somehow anything along these lines seems like it would inevitably be
> fairly icky.
>
> 'for' clauses could maybe also be used after the 'private' and 'protected'
>  keywords, to specify members that could only be access in a particular
> state.  Perhaps the nominal initialization point for data members only
> accessible in a particular state would be the first time the state was
> entered.
This bit would mean you would have to have some kind of (or new kind of)
ctors that let you initialize member later than at the point construction
like now. Things like this have far reaching implications. You cannot
just ad
hoc add anything you wish into the language without making the new thing
play
nice with the rest of it.

>
>> What you propose is just syntactic sugar and I do not see any pressing
>> need for it anywhere. In fact, I think that the usefulness of this
>> feature is very limited.
Again, I am still very skeptical about this. IMHO such specialized feature
has no place in general purpose language like C++. Everything you
propose can
be done (as demonstrated) using existing means and features of C++ fairly
easily. There are existing design patterns that let you do this kind of
thing
in any language even. E.g. double dispatch, visitor.

--
VH

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Walt <wkaras@yahoo.com>
Date: Mon, 30 Mar 2009 18:40:22 CST
Raw View
On Mar 29, 5:52 pm, Vaclav Haisman <v.hais...@sh.cvut.cz> wrote:
> Walt wrote, On 28.3.2009 19:45:
>
> > On Mar 27, 1:10 am, Vaclav Haisman <v.hais...@sh.cvut.cz> wrote:
> >> W Karas wrote, On 26.3.2009 1:28:>[...]
>
> >> This is something that can be done entirely using the current language
> >> as it is.
>
> > Well, of course there are many features of C++ that "can be done entirely"
> >  using the features of C.  Run time polymorphism is an example, it can be
> >  done with explicit vtables and vpointers.
>
> > One way to get the effect of what I propose is with a 'state' data member
> >  and switch statements in member functions, something like:
>
> > int X::x(char a, double b) { switch (this->state) { case S1:
> > return(`this->x_S1(a, b)); case S2: case S3:  return(this->x_S2_S3(a, b));
> >  ... } }
>
> > instead of (assuming S2 is the default state):
>
> > virtual int X::x(char a, double b) for S1 { ... }
>
> > virtual int X::x(char a, double b) for default, S3 { ... }
>
> You do not need even need switch to do that, you can use lookup table of
> your
> own. All you need is a table of structures with member function pointers.
>
> struct X
> {
> struct MyVMT
> {
>    int (X::* foo)(char, double);
>
> };
>
> enum State
> {
>    S1, S2
>
> };
>
> State state;
> static MyVMT const vmt[2];
>
> int foo(char c, double d)
> {
>    return (this->*vmt[state].foo) (c, d);
>
> }
>
> private:
> int foo_S1 (char, double);
> int foo_S2 (char, double);
>
> };
>
> X::MyVMT const X::vmt[2] = { { &X::foo_S1 }, { &X::foo_S2 } };

This looks like an explicit vtable of arrays.  I was thinking the
implementation would be simply switching vtables as the state
changed.  I think you are somewhat illustrating my point, that what
I'm proposing is a natural extension of existing C++ polymorphism.

>
>
>
>
>
> > (A small change here from the OP, using the reserve word 'default' for the
> >  default state instead of the numeral 0.  For convenience and
> > backwards-compatibility, a member function with no 'for' clause has the
> > same definition in all states.)
>
> > So yes, this feature would have to be useful fairly often for it to be
> > worth it.  Conceptually, one can see reasons that it might be used
> > frequently.  For example, in a simulation of some human social group or
> > organization that covered many decades of time.  The behavior of a
> > particular "human" object could change drastically depending on whether
> > the human being represented was a baby, young child, teenager, young
> > adult, etc.  You could maybe try to do this using multiple classes with a
> >  common base class, like:
>
> > human_p = teenager_p = new Teenager(child_p); delete child_p;
>
> > But somehow anything along these lines seems like it would inevitably be
> > fairly icky.
>
> > 'for' clauses could maybe also be used after the 'private' and 'protected'
> >  keywords, to specify members that could only be access in a particular
> > state.  Perhaps the nominal initialization point for data members only
> > accessible in a particular state would be the first time the state was
> > entered.
>
> This bit would mean you would have to have some kind of (or new kind of)
> ctors that let you initialize member later than at the point construction
> like now. Things like this have far reaching implications. You cannot
> just ad
> hoc add anything you wish into the language without making the new thing
> play
> nice with the rest of it.

I don't see the complexity that you seem to be seeing.  In some cases,
the class might need an implicit bitmap of states that have been
entered at least once.  The calls to the ctors of the state-specific
members would have to be within an implicit if-statement that checks
it the state has been entered before.  And this code would have to be
duplicated at each point where the state is entered.

I don't claim to be a leading expert in C++, or that my suggestions
might not lead to unexpected conundrums when interacting with existing
C++ features.  My hope is that people that who have more expertise in
the language will be intrigued by my suggestions, think of ways to
enhance them, and help find any conundrums.



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Tue, 31 Mar 2009 16:48:47 CST
Raw View
wkaras@yahoo.com (W Karas) wrote (abridged):
> Virtual functions could have multiple definitions, for different
> object states.

This sounds a bit like the feature Predicate Classes, found in, for
example, the language Cecil. See for example:

http://web.archive.org/web/20020112001033/www.cs.washington.edu/research/
projects/cecil/www/Papers/predicate-classes.html

     By associating methods with predicate classes, method lookup
     can depend not only on the dynamic class of an argument but
     also on its dynamic value or state.

As others have said, I don't think it offers enough bang for buck to be
added to C++.

-- Dave Harris, Nottingham, UK.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]