www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - typeid( identifier ) usage

reply Derek Parnell <derek psych.ward> writes:
I was hoping to use a simple method to determine the real typeid of a
variable at runtime using the code example below...

<code>
 class GenClass {}

 class Foo: GenClass {}

 class Bar: GenClass {}

 void main()
 {
    GenClass a = new Foo;
    GenClass b = new Bar;

    if (typeid(a) is typeid(Foo))
        printf("a is a Foo\n");
 }
</code>

But this fails to compile, giving the error message "test2.d(12): a is used
as a type". Which is exactly as the specification says it should. 

So I did get a workaround going by doing this ...

<code>
 class GenClass { abstract TypeInfo datatype();}

 class Foo: GenClass {  TypeInfo datatype() { return typeid(Foo);} }

 class Bar: GenClass { TypeInfo datatype() { return typeid(Bar);} }

 void main()
 {
    GenClass f = new Foo;
    GenClass b = new Bar;

    if (f.datatype is typeid(Foo))
        printf("f is a Foo\n");
    if (b.datatype is typeid(Bar))
        printf("b is a Bar\n");
 }
</code>

I also tried an alternative workaround, which also worked ...

<code>
 class GenClass: ClassInfo {this(){name = "GenClass";}}

 class Foo: GenClass {  this(){name = "Foo";} }

 class Bar: GenClass {  this(){name = "Bar";} }

 void main()
 {
    GenClass f = new Foo;
    GenClass b = new Bar;
    GenClass g = new GenClass;

    printf("f is a %.*s\n", f.name);
    printf("b is a %.*s\n", b.name);
    printf("g is a %.*s\n", g.name);
 }
</code>

but this doesn't make GenClass an abstract one.

So (finally) my questions are ... Is there a better way to do this sort of
thing, and if not, which of the two ways above is better?

-- 
Derek
Melbourne, Australia
21/Jul/04 11:29:24 AM
Jul 20 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
How about...

class GenClass {}

class Foo: GenClass {}

class Bar: GenClass {}

void main()
{
	GenClass a = new Foo;
	GenClass b = new Bar;

	if (cast(Foo)a) printf("a is a Foo\n");
	if (cast(Foo)b) printf("b is a Foo\n");
	if (cast(Bar)a) printf("a is a Bar\n");
	if (cast(Bar)b) printf("b is a Bar\n");
}

Regan

On Wed, 21 Jul 2004 11:43:09 +1000, Derek Parnell <derek psych.ward> wrote:

 I was hoping to use a simple method to determine the real typeid of a
 variable at runtime using the code example below...

 <code>
  class GenClass {}

  class Foo: GenClass {}

  class Bar: GenClass {}

  void main()
  {
     GenClass a = new Foo;
     GenClass b = new Bar;

     if (typeid(a) is typeid(Foo))
         printf("a is a Foo\n");
  }
 </code>

 But this fails to compile, giving the error message "test2.d(12): a is 
 used
 as a type". Which is exactly as the specification says it should.

 So I did get a workaround going by doing this ...

 <code>
  class GenClass { abstract TypeInfo datatype();}

  class Foo: GenClass {  TypeInfo datatype() { return typeid(Foo);} }

  class Bar: GenClass { TypeInfo datatype() { return typeid(Bar);} }

  void main()
  {
     GenClass f = new Foo;
     GenClass b = new Bar;

     if (f.datatype is typeid(Foo))
         printf("f is a Foo\n");
     if (b.datatype is typeid(Bar))
         printf("b is a Bar\n");
  }
 </code>

 I also tried an alternative workaround, which also worked ...

 <code>
  class GenClass: ClassInfo {this(){name = "GenClass";}}

  class Foo: GenClass {  this(){name = "Foo";} }

  class Bar: GenClass {  this(){name = "Bar";} }

  void main()
  {
     GenClass f = new Foo;
     GenClass b = new Bar;
     GenClass g = new GenClass;

     printf("f is a %.*s\n", f.name);
     printf("b is a %.*s\n", b.name);
     printf("g is a %.*s\n", g.name);
  }
 </code>

 but this doesn't make GenClass an abstract one.

 So (finally) my questions are ... Is there a better way to do this sort 
 of
 thing, and if not, which of the two ways above is better?

-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 20 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 21 Jul 2004 13:57:20 +1200, Regan Heath wrote:

 How about...
 
 class GenClass {}
 
 class Foo: GenClass {}
 
 class Bar: GenClass {}
 
 void main()
 {
 	GenClass a = new Foo;
 	GenClass b = new Bar;
 
 	if (cast(Foo)a) printf("a is a Foo\n");
 	if (cast(Foo)b) printf("b is a Foo\n");
 	if (cast(Bar)a) printf("a is a Bar\n");
 	if (cast(Bar)b) printf("b is a Bar\n");
 }
 

Thanks. This is almost right for me. I didn't realize that 'cast' returns a NULL if it fails to cast correctly. Anyhow, this is almost right except that it can still produce some ambiguous results... if (cast(GenClass)b) printf("b is a GenClass\n"); if (cast(Bar)b) printf("b is a Bar\n"); Thus 'b' is reported as being both 'GenClass' and 'Bar'. Whereas I think that 'b' *is* specifically (or more precisely) a 'Bar', but it is only a type of 'GenClass'. The method's I tried would only report it as being one type of class without ambiguity. But thanks for the info. -- Derek Melbourne, Australia 21/Jul/04 12:41:23 PM
Jul 20 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 21 Jul 2004 12:47:12 +1000, Derek Parnell <derek psych.ward> wrote:
 On Wed, 21 Jul 2004 13:57:20 +1200, Regan Heath wrote:

 How about...

 class GenClass {}

 class Foo: GenClass {}

 class Bar: GenClass {}

 void main()
 {
 	GenClass a = new Foo;
 	GenClass b = new Bar;

 	if (cast(Foo)a) printf("a is a Foo\n");
 	if (cast(Foo)b) printf("b is a Foo\n");
 	if (cast(Bar)a) printf("a is a Bar\n");
 	if (cast(Bar)b) printf("b is a Bar\n");
 }

Thanks. This is almost right for me. I didn't realize that 'cast' returns a NULL if it fails to cast correctly. Anyhow, this is almost right except that it can still produce some ambiguous results... if (cast(GenClass)b) printf("b is a GenClass\n"); if (cast(Bar)b) printf("b is a Bar\n"); Thus 'b' is reported as being both 'GenClass' and 'Bar'. Whereas I think that 'b' *is* specifically (or more precisely) a 'Bar', but it is only a type of 'GenClass'.

'b' itself is a reference to a GenClass. The thing it references is a Bar. It would be nice to be able to get those two pieces of info, at present we only get the type of the reference eg. "typeid(typeof(b)) is typeid(GenClass)"
 The method's I tried would only report it as being one type of class
 without ambiguity.

Can I ask why you need this? For logging purposes perhaps? Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 20 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 21 Jul 2004 15:19:37 +1200, Regan Heath wrote:

 On Wed, 21 Jul 2004 12:47:12 +1000, Derek Parnell <derek psych.ward> wrote:
 On Wed, 21 Jul 2004 13:57:20 +1200, Regan Heath wrote:

 How about...

 class GenClass {}

 class Foo: GenClass {}

 class Bar: GenClass {}

 void main()
 {
 	GenClass a = new Foo;
 	GenClass b = new Bar;

 	if (cast(Foo)a) printf("a is a Foo\n");
 	if (cast(Foo)b) printf("b is a Foo\n");
 	if (cast(Bar)a) printf("a is a Bar\n");
 	if (cast(Bar)b) printf("b is a Bar\n");
 }

Thanks. This is almost right for me. I didn't realize that 'cast' returns a NULL if it fails to cast correctly. Anyhow, this is almost right except that it can still produce some ambiguous results... if (cast(GenClass)b) printf("b is a GenClass\n"); if (cast(Bar)b) printf("b is a Bar\n"); Thus 'b' is reported as being both 'GenClass' and 'Bar'. Whereas I think that 'b' *is* specifically (or more precisely) a 'Bar', but it is only a type of 'GenClass'.

'b' itself is a reference to a GenClass. The thing it references is a Bar. It would be nice to be able to get those two pieces of info, at present we only get the type of the reference eg. "typeid(typeof(b)) is typeid(GenClass)"

Yeah I tried that too, but as you hinted, its usage is a bit limited. Interestingly, if you do something like ... GenClass b = new Bar; GenClass gc; gc = cast(GenClass)b; then you can still access the Bar members that override GenClass members via 'gc' even though 'gc' is not a Bar class. In other words, cast does not actually *convert* it to a GenClass, it just let's the compiler pretend that is a GenClass but its still really a Bar.
 The method's I tried would only report it as being one type of class
 without ambiguity.

Can I ask why you need this? For logging purposes perhaps?

I'm working on a 'compiler' for the Euphoria programming language that will use D as the intermediate language. Eu --> D --> obj --> exe. Euphoria supports 'variant' type variables and I'm experimenting with different ways to implement these in D. I have one implementation that works very well, and now I'm trying out some optimizations. -- Derek Melbourne, Australia 21/Jul/04 1:56:34 PM
Jul 20 2004
parent Regan Heath <regan netwin.co.nz> writes:
On Wed, 21 Jul 2004 14:21:11 +1000, Derek Parnell <derek psych.ward> wrote:
 On Wed, 21 Jul 2004 15:19:37 +1200, Regan Heath wrote:

 On Wed, 21 Jul 2004 12:47:12 +1000, Derek Parnell <derek psych.ward> 
 wrote:
 On Wed, 21 Jul 2004 13:57:20 +1200, Regan Heath wrote:

 How about...

 class GenClass {}

 class Foo: GenClass {}

 class Bar: GenClass {}

 void main()
 {
 	GenClass a = new Foo;
 	GenClass b = new Bar;

 	if (cast(Foo)a) printf("a is a Foo\n");
 	if (cast(Foo)b) printf("b is a Foo\n");
 	if (cast(Bar)a) printf("a is a Bar\n");
 	if (cast(Bar)b) printf("b is a Bar\n");
 }

Thanks. This is almost right for me. I didn't realize that 'cast' returns a NULL if it fails to cast correctly. Anyhow, this is almost right except that it can still produce some ambiguous results... if (cast(GenClass)b) printf("b is a GenClass\n"); if (cast(Bar)b) printf("b is a Bar\n"); Thus 'b' is reported as being both 'GenClass' and 'Bar'. Whereas I think that 'b' *is* specifically (or more precisely) a 'Bar', but it is only a type of 'GenClass'.

'b' itself is a reference to a GenClass. The thing it references is a Bar. It would be nice to be able to get those two pieces of info, at present we only get the type of the reference eg. "typeid(typeof(b)) is typeid(GenClass)"

Yeah I tried that too, but as you hinted, its usage is a bit limited. Interestingly, if you do something like ... GenClass b = new Bar; GenClass gc; gc = cast(GenClass)b;

You don't need the cast. This
    gc = b;

works.
 then you can still access the Bar members that override GenClass members
 via 'gc' even though 'gc' is not a Bar class.

Neither is 'b'. Both of them are GenClass _references_ to _something_ which must be a GenClass or one of it's derivatives.
 In other words, cast does not
 actually *convert* it to a GenClass, it just let's the compiler pretend
 that is a GenClass but its still really a Bar.

I think it's more that a GenClass reference, when it refers to a derivative of GenClass can access that derivatives members.
 The method's I tried would only report it as being one type of class
 without ambiguity.

Can I ask why you need this? For logging purposes perhaps?

I'm working on a 'compiler' for the Euphoria programming language that will use D as the intermediate language. Eu --> D --> obj --> exe. Euphoria supports 'variant' type variables and I'm experimenting with different ways to implement these in D. I have one implementation that works very well, and now I'm trying out some optimizations.

That sounds quite cool. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 20 2004
prev sibling next sibling parent reply Andrew Edwards <ridimz_at yahoo.dot.com> writes:
Derek Parnell wrote:
 I was hoping to use a simple method to determine the real typeid of a
 variable at runtime using the code example below...
 
 <code>
  class GenClass {}
 
  class Foo: GenClass {}
 
  class Bar: GenClass {}
 
  void main()
  {
     GenClass a = new Foo;
     GenClass b = new Bar;
 
     if (typeid(a) is typeid(Foo))

This is as simple as it gets: if (typeid(typeof(a)) is typeid(Foo))
         printf("a is a Foo\n");
  }
 </code>
 
 But this fails to compile, giving the error message "test2.d(12): a is used
 as a type". Which is exactly as the specification says it should. 
 
 So I did get a workaround going by doing this ...
 
 <code>
  class GenClass { abstract TypeInfo datatype();}
 
  class Foo: GenClass {  TypeInfo datatype() { return typeid(Foo);} }
 
  class Bar: GenClass { TypeInfo datatype() { return typeid(Bar);} }
 
  void main()
  {
     GenClass f = new Foo;
     GenClass b = new Bar;
 
     if (f.datatype is typeid(Foo))
         printf("f is a Foo\n");
     if (b.datatype is typeid(Bar))
         printf("b is a Bar\n");
  }
 </code>
 
 I also tried an alternative workaround, which also worked ...
 
 <code>
  class GenClass: ClassInfo {this(){name = "GenClass";}}
 
  class Foo: GenClass {  this(){name = "Foo";} }
 
  class Bar: GenClass {  this(){name = "Bar";} }
 
  void main()
  {
     GenClass f = new Foo;
     GenClass b = new Bar;
     GenClass g = new GenClass;
 
     printf("f is a %.*s\n", f.name);
     printf("b is a %.*s\n", b.name);
     printf("g is a %.*s\n", g.name);
  }
 </code>
 
 but this doesn't make GenClass an abstract one.
 
 So (finally) my questions are ... Is there a better way to do this sort of
 thing, and if not, which of the two ways above is better?
 

Jul 20 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 21 Jul 2004 00:13:25 -0400, Andrew Edwards wrote:

 Derek Parnell wrote:
 I was hoping to use a simple method to determine the real typeid of a
 variable at runtime using the code example below...
 
 <code>
  class GenClass {}
 
  class Foo: GenClass {}
 
  class Bar: GenClass {}
 
  void main()
  {
     GenClass a = new Foo;
     GenClass b = new Bar;
 
     if (typeid(a) is typeid(Foo))

This is as simple as it gets: if (typeid(typeof(a)) is typeid(Foo)) printf("a is a Foo\n");

Except that this doesn't work as expected. 'typeid(typeof(a))' returns 'typeid(GenClass)' and not 'typeid(Foo)'. -- Derek Melbourne, Australia 21/Jul/04 2:25:15 PM
Jul 20 2004
next sibling parent Andrew Edwards <ridimz_at yahoo.dot.com> writes:
Derek Parnell wrote:
 On Wed, 21 Jul 2004 00:13:25 -0400, Andrew Edwards wrote:
 
 
Derek Parnell wrote:

I was hoping to use a simple method to determine the real typeid of a
variable at runtime using the code example below...

<code>
 class GenClass {}

 class Foo: GenClass {}

 class Bar: GenClass {}

 void main()
 {
    GenClass a = new Foo;
    GenClass b = new Bar;

    if (typeid(a) is typeid(Foo))

This is as simple as it gets: if (typeid(typeof(a)) is typeid(Foo)) printf("a is a Foo\n");

Except that this doesn't work as expected. 'typeid(typeof(a))' returns 'typeid(GenClass)' and not 'typeid(Foo)'.

I C. Thanks for the clarification!
Jul 20 2004
prev sibling parent Regan Heath <regan netwin.co.nz> writes:
On Wed, 21 Jul 2004 14:27:57 +1000, Derek Parnell <derek psych.ward> wrote:

 On Wed, 21 Jul 2004 00:13:25 -0400, Andrew Edwards wrote:

 Derek Parnell wrote:
 I was hoping to use a simple method to determine the real typeid of a
 variable at runtime using the code example below...

 <code>
  class GenClass {}

  class Foo: GenClass {}

  class Bar: GenClass {}

  void main()
  {
     GenClass a = new Foo;
     GenClass b = new Bar;

     if (typeid(a) is typeid(Foo))

This is as simple as it gets: if (typeid(typeof(a)) is typeid(Foo)) printf("a is a Foo\n");

Except that this doesn't work as expected. 'typeid(typeof(a))' returns 'typeid(GenClass)' and not 'typeid(Foo)'.

Technically 'a' is a GenClass _reference_ so typeof(a) should return 'GenClass'. What you really want to be able to ask is "what type does 'a' refer to?" Take 'int' and 'int*' for example int a; int *b = &a; typeof(a) is 'int' typeof(b) is 'int*' typeof(*b) is 'int' you can't do the same with a class reference however. :) Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 20 2004
prev sibling parent reply Andy Friesen <andy ikagames.com> writes:
Derek Parnell wrote:
 I was hoping to use a simple method to determine the real typeid of a
 variable at runtime using the code example below...
 
 but this doesn't make GenClass an abstract one.
 
 So (finally) my questions are ... Is there a better way to do this sort of
 thing, and if not, which of the two ways above is better?

You can use ClassInfo instead. All reference types have a polymorphic classinfo reference which describes most of the important things. -- andy
Jul 20 2004
parent Derek Parnell <derek psych.ward> writes:
On Tue, 20 Jul 2004 23:13:28 -0700, Andy Friesen wrote:

 Derek Parnell wrote:
 I was hoping to use a simple method to determine the real typeid of a
 variable at runtime using the code example below...
 
 but this doesn't make GenClass an abstract one.
 
 So (finally) my questions are ... Is there a better way to do this sort of
 thing, and if not, which of the two ways above is better?

You can use ClassInfo instead. All reference types have a polymorphic classinfo reference which describes most of the important things.

Hi Andy, thanks heaps. After discovering that 'classinfo' is not documented anywhere useful, I resorted to wading through the phobos source code to see how it can be used. I don't understand how it works (magic comes to mind), but its usage seems clear enough. So now I've got this ... <code> class GenClass {char[] typename() {return this.classinfo.name;}} class Foo: GenClass {} class Bar: GenClass {} class XYZ: Bar {} void main() { GenClass f = new Foo; GenClass b = new Bar; GenClass g = new GenClass; GenClass x = new XYZ; printf("f is a %.*s\n", f.typename); printf("b is a %.*s\n", b.typename); printf("g is a %.*s\n", g.typename); printf("x is a %.*s\n", x.typename); } </code> which is simple and it works. -- Derek Melbourne, Australia 21/Jul/04 5:00:14 PM
Jul 21 2004