Topic: assignment to 'this


Author: kin@isi.com (Kin Cho)
Date: 5 Feb 1993 21:38:30 GMT
Raw View
The C++ 2.1 change (from 2.0) that really hurt our application is
the disallowing of assignment to 'this'.  Here's why:

In the runtime engine of my application, which is a language interpreter,
an executing routine is described by an object, and the call-chain is
thus a linked list of these executing routines.

class routine {
   enum instructions  {LOD,STO,CALL,RET,...};
   instructions *instr;
   routine *caller;
public:
   void run();
};

void routine::run()
{
   for (;;) {
   switch (*instr++) {
   case LOD:
      ...
      break;
   case STO:
      ...
      break;
   case CALL:
      ...
      this = new routine(this,...);
      break;
   case RET:
      ...
      routine *save_this = this;
      this = caller;
      delete save_this;
      break;
   }
   }
}

So being able to assign to 'this' really makes the code mirror the semantics.
Note that doing a procedure call instead of assigning to 'this' is not a
viable solution, even if the stack-growth is not a problem in recursive
CALL's, routine::run must be suspendable for the purpose of supporting
a debugger.

I think allowing some mechanism whereby 'this' can be modified has a
legitimate place in the language.

--
-kin

kin@isi.com

Kin Cho
Integrated Systems Inc.
(408) 980-1500 ext. 230
Fax (408) 980-0400




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: 7 Feb 93 16:03:54 GMT
Raw View
kin@isi.com (Kin Cho) writes:

>The C++ 2.1 change (from 2.0) that really hurt our application is
>the disallowing of assignment to 'this'.  Here's why:
>
>In the runtime engine of my application, which is a language interpreter,
>an executing routine is described by an object, and the call-chain is
>thus a linked list of these executing routines.
>
>class routine {
>   enum instructions  {LOD,STO,CALL,RET,...};
>   instructions *instr;
>   routine *caller;
>public:
>   void run();
>};
>
>void routine::run()
>{
>   for (;;) {
>   switch (*instr++) {
>   case LOD:
>      ...
>      break;
>   case STO:
>      ...
>      break;
>   case CALL:
>      ...
>      this = new routine(this,...);
>      break;
>   case RET:
>      ...
>      routine *save_this = this;
>      this = caller;
>      delete save_this;
>      break;
>   }
>   }
>}
>
>So being able to assign to 'this' really makes the code mirror the semantics.
>Note that doing a procedure call instead of assigning to 'this' is not a
>viable solution, even if the stack-growth is not a problem in recursive
>CALL's, routine::run must be suspendable for the purpose of supporting
>a debugger.

One simple solution is to declare a routine pointer 'r' to use instead of
using 'this'. The code then looks like this:

 void routine::run()
 {
     routine *r = this;
     for (;;) {
     switch (*r->instr++) {
     case LOD:
        ...
        break;
     case STO:
        ...
        break;
     case CALL:
        ...
        r = new routine(r,...);
        break;
     case RET:
        ...
        routine *save_r = r;
        r = r->caller;
        delete save_r;
        break;
     }
     }
  }

The only disadvantage with this is that you need to insert r-> in front
of all the references to member functions/variables. You could avoid
this by separating the code for LOD, STO, etc. into (inline) functions
lod(), sto(), etc.:

 inline void routine::lod() { ... }
 inline void routine::sto() { ... }
 ...
     case LOD:
        r->lod();
        break;
     case STO:
        r->lod();
        break;
--
Fergus Henderson             fjh@munta.cs.mu.OZ.AU
This .signature virus is a self-referential statement that is true - but
you will only be able to consistently believe it if you copy it to your own
.signature file!




Author: hendrik@vedge.com (Hendrik Boom)
Date: 8 Feb 93 14:39:07 GMT
Raw View
kin@isi.com (Kin Cho) writes:
: The C++ 2.1 change (from 2.0) that really hurt our application is
: the disallowing of assignment to 'this'.  Here's why:
:
: In the runtime engine of my application, which is a language interpreter,
: an executing routine is described by an object, and the call-chain is
: thus a linked list of these executing routines.
:
: class routine {
:    enum instructions  {LOD,STO,CALL,RET,...};
:    instructions *instr;
:    routine *caller;
: public:
:    void run();
: };
:
: void routine::run()
: {
:    for (;;) {
:    switch (*instr++) {
:    case LOD:
:       ...
:       break;
:    case STO:
:       ...
:       break;
:    case CALL:
:       ...
:       this = new routine(this,...);
:       break;
:    case RET:
:       ...
:       routine *save_this = this;
:       this = caller;
:       delete save_this;
:       break;
:    }
:    }
: }
:
: So being able to assign to 'this' really makes the code mirror the semantics.
: Note that doing a procedure call instead of assigning to 'this' is not a
: viable solution, even if the stack-growth is not a problem in recursive
: CALL's, routine::run must be suspendable for the purpose of supporting
: a debugger.
:
: I think allowing some mechanism whereby 'this' can be modified has a
: legitimate place in the language.
:
: --
: -kin
:
: kin@isi.com
:
: Kin Cho
: Integrated Systems Inc.
: (408) 980-1500 ext. 230
: Fax (408) 980-0400

It's not at all obvious why any variable name other than 'this'
(perhaps 'that" :-) ) wouldn't do as well, except that you would
have to explicitly prefix a lot of member names with 'that'.

Presumably 'run' would then become a static member.
--
-------------------------------------------------------
Try one or more of the following addresses to reply.
at work: hendrik@vedge.com,  iros1!vedge!hendrik
at home: uunet!ozrout!topoi!hendrik