digitalmars.D.learn - template returning delegate
- Marek Janukowicz (54/54) Aug 21 2013 Yet another problem I just spotted:
- Marek Janukowicz (6/6) Aug 21 2013 After I sent the message I realized my limited English knowledge made me...
- Marek Janukowicz (34/101) Aug 21 2013 `_D6member23__T5templTS6member3ValZ5templFNfS6member3ValAyaZDFZAya9__lam...
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__T5templTS6member3ValZ5templFNfS6member3ValAyaZDFZ ya9__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__T5templTS6member3ValZ5templFNfS6member3ValAyaZDFZ ya9__lambda1MFZAya' changed from 32 in member.o to 33 in member.o 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. -- Marek Janukowicz
Aug 21 2013
After I sent the message I realized my limited English knowledge made me make a subject that actually had quite a different meaning than I intended :) Now it's hopefully fine or at least less ambiguous. -- Marek Janukowicz
Aug 21 2013
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 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
Aug 21 2013