| |
 | Posted by Marek Janukowicz in reply to Marek Janukowicz | Permalink Reply |
|
Marek Janukowicz 
Posted in reply to Marek Janukowicz
| Marek Janukowicz wrote:
> Yet another problem I just spotted:
>
> -----------------------
>
> import std.stdio, std.string;
>
> struct Val {
> int i;
> byte b;
> }
>
> template templ( T ) {
>
> auto templ (T obj, string name) {
> foreach( s; __traits(derivedMembers, T)) {
> if (s == name) {
> static if( is(typeof(__traits(getAttributes, __traits(getMember,
> T,
> s))) blah)) { // Rule out "non-regular" members
> //return format( "%s", __traits(getMember, obj, s)); // Version
> A return cast(string delegate())() { return
> format("%s",__traits(getMember, obj, s)); }; // Version B
> }
> }
> }
> throw new Exception("Invalid member");
> }
> }
>
> void main (string [] args) {
> Val v = Val(1, 2);
> //writefln( "%s: %s", args[1], templ!()(v, args[1])); // Version A
> writefln( "%s: %s", args[1], templ!()(v, args[1])()); // Version B
> }
>
> ---------------------------
>
> Now running:
> $ dmd -run member.d i
> /usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/../../../../x86_64-pc-linux-
> gnu/bin/ld: Warning: size of symbol
>
`_D6member23__T5templTS6member3ValZ5templFNfS6member3ValAyaZDFZAya9__lambda1MFZAya'
> changed from 32 in member.o to 33 in member.o
> i: 1
>
> $ dmd -run member.d b /usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/../../../../x86_64-pc-linux- gnu/bin/ld: Warning: size of symbol
>
`_D6member23__T5templTS6member3ValZ5templFNfS6member3ValAyaZDFZAya9__lambda1MFZAya'
> changed from 32 in member.o to 33 in member.o
> b: 1 # Why not 2?
>
> If I compile using ldc2 I get exactly the same result, so the delegate returned from template always returns value of "i" member (maybe it's always the first member that is returned). Ld warning is not present then.
>
> However if I comment "Version B" lines and uncomment "Version A" (which means I return the result directly instead of returning the delegate I get expected results:
>
> $ dmd -run member.d i
> i: 1
>
> $ dmd -run member.d b
> b: 2
>
> Also no ld warning in this case.
Figured it out - this code works as expected:
import std.stdio, std.string;
struct Val {
int i;
byte b;
}
template templ( T ) {
auto dg(alias s)( T obj ) {
return () { return format("%s",__traits(getMember, obj, s)); };
}
auto templ (T obj, string name) {
foreach( s; __traits(derivedMembers, T)) {
if (s == name) {
static if( is(typeof(__traits(getAttributes, __traits(getMember, T,
s))) blah)) { // Rule out "non-regular" members
return dg!(s)(obj);
}
}
}
throw new Exception("Invalid member");
}
}
void main (string [] args) {
Val v = Val(1, 2);
writefln( "%s: %s", args[1], templ!()(v, args[1])());
}
My mistake was to return delegate with __traits directly inside, why the correct way to do this was to create delegate using template. However, now I'm a bit confused my code worked at all instead of failing right away.
--
Marek Janukowicz
|