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