Typeof woes

Marek Janukowicz marek at janukowicz.net
Tue Aug 20 23:32:09 PDT 2013


H. S. Teoh wrote:

> On Wed, Aug 21, 2013 at 01:42:11AM +0200, Marek Janukowicz wrote:
>> Given this short program:
>> 
>> class A {
>> 
>>   int i;
>>   //enum Smth { X };
>> 
>>   void list () {
>>     foreach( s; __traits(derivedMembers, typeof(this))) {
>>       alias type = typeof(__traits(getMember, this, s));
>>     }
>>   }
>> }
>> 
>> void main () {
>>   A a = new A();
>>   a.list();
>> }
>> 
>> if I uncomment "enum" line I get compilation error:
>> aa.d(8): Error: argument Smth to typeof is not an expression
>> 
>> So far it only happened with enums for me, but admittedly I didn't
>> check all the possible types out there.
> 
> The reason is that derivedMembers returns *all* members, including enum
> definitions, not just member variables and methods. So this includes
> 'Smth', and typeof(this.Smth) is invalid because this.Smth is already a
> type, so you can't apply typeof to it.

Yes, I do understand this, however the behavior indicated below (your last 
question and my code) got me really confused. 
> 
> To get around this, you will need to use static if, maybe something like
> this:
> 
> void list() {
> // Warning: untested code
> foreach(s; __traits(derivedMembers, typeof(this))) {
> static if (is(typeof(__traits(getMember, this, s)) type)) {
> // here, 'type' is bound to the type of
> // the member.
> }
> }
> }
> 
> This uses the is(X Y) form, where if X is a valid type, then it gets
> aliased to Y inside the static if block. (I have to admit I'm not that
> pleased with D's is-expressions due to their confusing syntax, but they
> do work and are quite a powerful tool to use once you understand them.)

This code works, thank you. However, if I may share my newbie impression - 
current traits implementation looks not complete to me. What I want to do is 
to process those members that are of certain type - instead of a nice one-
liner to identify those, I already need two and the first (the one you 
provided above) looks like a hack to me, because I have to check if some 
expression is valid. The whole issue (which to me looks like a quite 
standard metaprogramming task) already took me a few hours (and also some 
time of you and the other helpful guys) and I can't get rid of the 
impression either the docs are lacking or we could use some more traits.

>> What's even more interesting it's just alias problem, the expression
>> "typeof(__traits(getMember, this, s))" might be used eg. in static if
>> even for enums.
>> 
>> Is this a bug or do I miss something (again)?
> [...]
> 
> Are you sure about that? That doesn't sound right to me.

Yes, I'm sure, here goes modified code:
import std.stdio;

class A {

  int a;
  enum Smth { A };

  void list () {
    foreach( s; __traits(derivedMembers, typeof(this))) {
      //alias type = typeof(__traits(getMember, this, s));
      static if (is (typeof(__traits(getMember, this, s)) == int)) {
        writefln ("%s is int", s );
      }
    }
  }
}

void main () {
  A a = new A();
  a.list();
}

which outputs:
a is int

-- 
Marek Janukowicz


More information about the Digitalmars-d-learn mailing list