[comp.lang.c++] class "names" at runtime

psrc@pegasus.ATT.COM (Paul S. R. Chisholm) (12/15/89)

From article <22137@brunix.UUCP>, by sdm@cs.brown.edu (Scott Meyers):
> 2.  Add an enumerated type to ARC that enumerates each of the
> subtypes, and add a virtual function arc_type() that is redefined in
> each subclass to return the appropriate value.  Then I can write
> code like "if (arc->arc_type() == EXECUTABLE) arc->evaluate()".

In article <3164@cbnewsl.ATT.COM>, dog@cbnewsl.ATT.COM (edward.n.schiebel) writes:
> I found a need to do this once (or twice :-), but (as you mention later)
> it suffers from having to modify the base class when you derive a 
> new type from it.  I have a variation on this theme which does not
> suffer from this weakness:

> class base {
> public:
> 	virtual String type();
> };

Well, it's nice that the "class name" is printable, but it doesn't need
to be as flexible as a String.  In Smalltalk-80 (TM), there's a
subclass of String known as Symbol.  Symbols are implemented as
Strings, but are kept in a table so they're guaranteed unique.  Thus,
to compare two Symbols, all you have to do is compare the character
pointers (in C++; in Smalltalk-80, the "=" operator is the same as the
"==" operator, and you just see if two Symbols are identically the same
object, I think).

So let's say (I haven't run any of these through the compiler):

class base {
private:
	static char *Typename;	// initialized to "base" somewhere
	...
public:
	// type() -- return a pointer to a constant name
	virtual const char* type() {
		return Typename;	// that is, base::Typename
	};
	static const char* Stype() {
		return base::Typename;
	};
	...
};

> class derived : public base {
> pubic:
> 	static String Stype() {return type_string;}
> 	String type() {return Stype();}
> private:
> 	static String type_string; // initialized to "derived" in .c file
> };

class derived : public base {
private:
	static char Typename[];	// initialized to "derived" somewhere
	...
public:
	const char* type() {
		return Typename;	// that is, derived::Typename
	};
	static const char* Stype() {
		return derived::Typename;
	};
};

> Now the test becomes:
> 	if(base_ptr->type() == derived::Stype()) doSomething()
> (assuming class String has operator== defined of course).

> This test (a String comparison) is not that much more expensive than
> an integer test, since in many cases, the comparison will fail in the
> first character (unless your clas hierarchy looks like arc_generic, 
> arc_this, arc_that, arc_theotherthing).

The test base_ptr->type() == derived::Stype is just a comparison of two
pointers.  Can't put them in case statements, though.  And you'd better
get them right (re-implement it in every class)!

Turbo Pascal 5.5 has an interesting approach:  the "type name" is the
pointer to the "virtual method table", and every object of a virtual
class responds to the message "TypeOf".

> Ed Schiebel, AT&T Bell Laboratories, dog@vilya.att.com

Paul S. R. Chisholm, AT&T Bell Laboratories
att!pegasus!psrc, psrc@pegasus.att.com, AT&T Mail !psrchisholm
I'm not speaking for the company, I'm just speaking my mind.
Smalltalk-80 is a trademark of Parc Place Systems, or Xerox, or somebody.

jimad@microsoft.UUCP (Jim Adcock) (12/19/89)

One trick [from ObjC - gack!] is to maintain your names as pointers to
strings to begin with, but when you access that pointer the first time
you [automagically] change it to a handle for an entry in a lookup table.  
Since the table is a limited range of addresses, it is quick and easy to 
see if the conversion has already been done, and assuming it has been done, 
the comparison is just a pointer compare.  Since the entry in the table
is a string with the same characters, when you go back to a flat representation
of your object, you automatically change it back to a string representation
again.  The cost is a couple extra pointer checks to see if the string
is in the table [yet] or not.  Alternately maintain a hash of the string
and compare that.

rminnich@super.ORG (Ronald G Minnich) (01/03/90)

In article <10@microsoft.UUCP> jimad@microsoft.UUCP (Jim Adcock) writes:
>One trick [from ObjC - gack!] is to maintain your names as pointers to
>strings to begin with, but when you access that pointer the first time
>you [automagically] change it to a handle for an entry in a lookup table.  
>Since the table is a limited range of addresses, it is quick and easy to 
>see if the conversion has already been done, 
Anybody else out there recognize this one? 
To me, it looks just like the 'bundles' S.C. Johnson used in the
first YACC paper. 
A bundle was a pointer to some 'thing' or another bundle. You determined
what it was by checking to see if the pointer was in the range of addresses 
for the table of bundles or 'something else'. 
Just wondering if anyone else noticed this,
ron