On 04/01/12 08:18, Ali Çehreli wrote: > 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". eg: static if (!__traits(compiles, &__traits(getMember, obj, name))) or just static if (!is(typeof(member)))
>> 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. That's because the compiler won't accept "foreach (i, t; S.tupleof)" and "*.tupleof[i].stringof" is necessary to get the original name. This would have worked too: enum name = *s.tupleof[i].stringof[4..$]; but obfuscates the code more and looks like dereferencing a null pointer. artur