A template returning a delegate [was: template returning delegate]
Marek Janukowicz
marek at janukowicz.net
Wed Aug 21 17:45:37 PDT 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
> 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
More information about the Digitalmars-d-learn
mailing list