On 03/31/2012 09:09 PM, Artur Skawina wrote:
> On 03/31/12 21:09, Ali Çehreli wrote:
>> How can I determine just the data members of a struct or class, excluding the member functions? isCallable() comes short as member variable that have opCall() defined are also callable:
> [...]
>> Wait! I found a solution before sending this message. :P isIntegral() works:
>>
>>          if (isIntegral!(typeof(mixin("S." ~ member)))) {
>>
>> Now the output is:
>>
>>      i is a member function
>>      m is a member variable<-- good but dubious
>>    foo is a member variable
> [...]
>
> Don't forget about templates (appear as members too, but don't have a type).

I see. We can't even use isCallable or isIntegral with a template member. Assuming S has this member function template:

    void bar(T)()
    {}

Then we get the following error:

/usr/include/d/dmd/phobos/std/traits.d(3223): Error: (S).bar(T) has no value

I don't know a way of saying "if a template".

> This will print all fields of struct/class S:
>
>     enum s = cast(S*)null;
>     foreach (i, m; s.tupleof) {
>        enum name = S.tupleof[i].stringof[4..$];
>        alias typeof(m) type;
>        writef("(%s) %s\n", type.stringof, name);
>     }
>
> Real Programmers don't use std.traits. ;)
>
> artur

Your method works but needing to iterate on a struct variable by s.tupleof and having to use the struct type as S.tupleof in the loop body is strange.

Looks like S.tupleof[i].stringof is the answer for what I was looking for:

import std.stdio;
import std.traits;

struct M
{
    int i;

    this(int i)
    {
        this.i = i;
    }

    void opCall()
    {}
}

struct S
{
    int i;
    M m;

    void foo()
    {}

    void bar(T)()
    {}
}

void main()
{
    enum s = S(42, M(7));

    foreach (i, m; s.tupleof) {
        writefln("%s:", i);

        enum name = S.tupleof[i].stringof[4..$];
        alias typeof(m) type;
        writefln("  S.tupleof[i]: %s", S.tupleof[i].stringof);
        writefln("  (type) name : (%s) %s", type.stringof, name);

        writefln("  m           : %s", m);
        writefln("  m.stringof  : %s", m.stringof);
    }
}

The output:

0:
  S.tupleof[i]: (S).i
  (type) name : (int) i
  m           : 42
  m.stringof  : 42
1:
  S.tupleof[i]: (S).m
  (type) name : (M) m
  m           : M(7)
  m.stringof  : m

Ali

Reply via email to