Bug 1386 – "string expected" when using allMembers-element in __traits(getMember, ...)

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2007-07-30T12:34:00Z
Last change time
2015-06-09T01:14:15Z
Keywords
rejects-valid
Assigned to
nobody
Creator
jascha

Comments

Comment #0 by jascha — 2007-07-30T12:34:49Z
import std.stdio; struct Temp(T...) { alias void delegate(T) asdf; } class Asdf { Temp!(uint) asdf; Temp!(string) qwer; Temp!(real,real) yxcv; } void main() { foreach ( member; __traits(allMembers, Asdf) ) { Asdf a; writefln("%s %s", member, typeid(typeof(__traits(getMember, a, member)))); } }
Comment #1 by samukha — 2007-07-31T02:56:33Z
__traits works only with strings known at compile time and in your example 'member' is evaluated at run-time. However, allMembers trait evaluates to an array literal, so there should be a way to iterate through it at compile time. Unfortunately, D doesn't have true 'static foreach' and you probably have to resort to hacks.
Comment #2 by jascha — 2007-07-31T07:04:37Z
'member' should be evaluated at compile-time, since foreach usually works with CTFE. if not, the error should be "cannot evaluate ... at compile time".
Comment #3 by hoganmeier — 2009-04-01T13:25:26Z
I've tried everything to work around this, but nothing worked. In fact this prevents many thinkable uses of compile time introspection.
Comment #4 by dhasenan — 2009-04-01T17:44:34Z
Leave the version number on the _earliest_ dmd version exhibiting the problem.
Comment #5 by dhasenan — 2009-04-01T17:47:03Z
Also, you can work around this using a for-loop (I think) or recursive templates; and "blocker" refers to a bug sufficiently severe that Walter should drop everything else and fix this bug, or even possibly roll back to an earlier version that does not exhibit the bug.
Comment #6 by hoganmeier — 2009-04-01T17:54:55Z
Ok, sorry didn't know. Finally managed to compile a workaround: template Sequence(size_t count, size_t index = 0) { static if (index < count) alias Tuple!(index, Sequence!(count, index + 1)) Sequence; else alias Tuple!() Sequence; } static const members = __traits (allMembers, foo); foreach (i; Sequence!(members.length)) { foreach (p; ParameterTypeTuple!(__traits(getMember, foo, members[i]))) writefln(typeid(p)); }
Comment #7 by simen.kjaras — 2010-01-02T05:45:23Z
As a way to index allMembers as a tuple, here's a template converting an array known at compile time to a tuple: template ArrayToTuple( alias Arr, U... ) { static if ( Arr.length ) { alias ArrayToTuple!( Arr[ 0..$-1 ], Arr[ $-1 ], U ) ArrayToTuple; } else { alias U ArrayToTuple; } }
Comment #8 by hoganmeier — 2010-02-02T17:02:30Z
allMembers returns a tuple now (svn r360) but this still doesn't work. Yields a strange error.
Comment #9 by clugdbug — 2011-04-15T21:33:24Z
The error message is: test2.d(22): Error: no property '__T4TempTkZ' for type 'test2.Asdf' Some kind of junk tuple members are being included in allMembers.
Comment #10 by k.hara.pg — 2011-09-22T10:20:26Z
In 2.055, The problem in comment #9 does not occur by fixing bug 2234. Therefore original sample code in comment #0 might work as expected. But class has a member interface Monitor, so > typeid(typeof(__traits(getMember, a, member)))) will fail to compile. If you change `class Asdf` into `struct Asdf`, you'll get following output: asdf test.Temp!(uint).Temp qwer test.Temp!(string).Temp yxcv test.Temp!(real,real).Temp