digitalmars.D - Strange template problem
- Kirk McDonald (56/56) Jul 08 2006 I'm having some trouble with a very odd template problem. Take the
- Tom S (7/73) Jul 08 2006 MIN_ARGS is 0 for 'foo', because thats what the NumberOfArgs template
- Kirk McDonald (6/84) Jul 08 2006 --
- Kirk McDonald (26/113) Jul 08 2006 Actually, I think I'm going to be really pedantic and correct you:
- Tom S (24/64) Jul 08 2006 Thanks for correcting me and sorry for being dumb and answering too
- Bruno Medeiros (6/52) Jul 09 2006 For what I see, a function pointer *does* know about default arguments.
I'm having some trouble with a very odd template problem. Take the following code: [test.d] import std.stdio; import ftype; // Daniel Keep's ftype module // A function with default arguments void foo(int i=20, char[] s="Monkey") { writefln("foo: %s %s", i, s); } // A function with the same arguments and no defaults void bar(int i, char[] s) { writefln("bar: %s %s", i, s); } // A function that takes a function pointer and the minimum // number of arguments the function can be called with, and // calls it. void Baz(fn_t, uint MIN_ARGS)(fn_t fn) { static if (MIN_ARGS == 0) fn(); else static if (MIN_ARGS == 1) fn(10); else static if (MIN_ARGS == 2) fn(15, "Copper"); } // A template function that takes a function alias and the // minimum number of args it can be called with, and calls // Baz void Blah(alias Fn, uint MIN_ARGS = NumberOfArgs!(typeof(&Fn))) () { alias typeof(&Fn) fn_t; fn_t fn = &Fn; Baz!(fn_t, MIN_ARGS)(fn); } void main() { Blah!(bar); // Line 28 Blah!(foo, 0); // Line 29 } $ build test test.d(14): Error: expected 2 arguments, not 0 test.d(24): template instance test22.Baz!(void(*)(int i, char[] s),0u) error instantiating test.d(29): template instance test22.Blah!(foo,0) error instantiating Curiously, this works if I comment out line 28: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test foo: 20 Monkey It also works if I comment out line 29 instead: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test bar: 15 Copper But if both lines are there together, it fails. -- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wiki
Jul 08 2006
Kirk McDonald wrote:I'm having some trouble with a very odd template problem. Take the following code: [test.d] import std.stdio; import ftype; // Daniel Keep's ftype module // A function with default arguments void foo(int i=20, char[] s="Monkey") { writefln("foo: %s %s", i, s); } // A function with the same arguments and no defaults void bar(int i, char[] s) { writefln("bar: %s %s", i, s); } // A function that takes a function pointer and the minimum // number of arguments the function can be called with, and // calls it. void Baz(fn_t, uint MIN_ARGS)(fn_t fn) { static if (MIN_ARGS == 0) fn();MIN_ARGS is 0 for 'foo', because thats what the NumberOfArgs template returns, using the function *alias*. the *type* doesnt tell the compiler that it can be called with no args. thats just a func type that takes two args. thus the error.else static if (MIN_ARGS == 1) fn(10); else static if (MIN_ARGS == 2) fn(15, "Copper"); } // A template function that takes a function alias and the // minimum number of args it can be called with, and calls // Baz void Blah(alias Fn, uint MIN_ARGS = NumberOfArgs!(typeof(&Fn))) () { alias typeof(&Fn) fn_t; fn_t fn = &Fn; Baz!(fn_t, MIN_ARGS)(fn); } void main() { Blah!(bar); // Line 28 Blah!(foo, 0); // Line 29 } $ build test test.d(14): Error: expected 2 arguments, not 0 test.d(24): template instance test22.Baz!(void(*)(int i, char[] s),0u) error instantiating test.d(29): template instance test22.Blah!(foo,0) error instantiating Curiously, this works if I comment out line 28: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test foo: 20 Monkey It also works if I comment out line 29 instead: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test bar: 15 Copper But if both lines are there together, it fails.-- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jul 08 2006
Tom S wrote:Kirk McDonald wrote:Then why does it work when I comment out line 28?I'm having some trouble with a very odd template problem. Take the following code: [test.d] import std.stdio; import ftype; // Daniel Keep's ftype module // A function with default arguments void foo(int i=20, char[] s="Monkey") { writefln("foo: %s %s", i, s); } // A function with the same arguments and no defaults void bar(int i, char[] s) { writefln("bar: %s %s", i, s); } // A function that takes a function pointer and the minimum // number of arguments the function can be called with, and // calls it. void Baz(fn_t, uint MIN_ARGS)(fn_t fn) { static if (MIN_ARGS == 0) fn();MIN_ARGS is 0 for 'foo', because thats what the NumberOfArgs template returns, using the function *alias*. the *type* doesnt tell the compiler that it can be called with no args. thats just a func type that takes two args. thus the error.-- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wikielse static if (MIN_ARGS == 1) fn(10); else static if (MIN_ARGS == 2) fn(15, "Copper"); } // A template function that takes a function alias and the // minimum number of args it can be called with, and calls // Baz void Blah(alias Fn, uint MIN_ARGS = NumberOfArgs!(typeof(&Fn))) () { alias typeof(&Fn) fn_t; fn_t fn = &Fn; Baz!(fn_t, MIN_ARGS)(fn); } void main() { Blah!(bar); // Line 28 Blah!(foo, 0); // Line 29 } $ build test test.d(14): Error: expected 2 arguments, not 0 test.d(24): template instance test22.Baz!(void(*)(int i, char[] s),0u) error instantiating test.d(29): template instance test22.Blah!(foo,0) error instantiating Curiously, this works if I comment out line 28: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test foo: 20 Monkey It also works if I comment out line 29 instead: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test bar: 15 Copper But if both lines are there together, it fails.
Jul 08 2006
Kirk McDonald wrote:Tom S wrote:Actually, I think I'm going to be really pedantic and correct you: MIN_ARGS is 0 for 'foo' because I explicitly told it to be (on line 29). NumberOfArgs would evaluate to 2, because it does indeed operate on the type of the function pointer, which doesn't know a thing about default arguments. If lines 28 and 29 instead read: Blah!(bar); Blah!(foo); Then it works just fine, calling both functions with two args: $ ./test bar: 15 Copper foo: 15 Copper But it also works when I comment out line 28 and say "Blah!(foo, 0)", which is slightly baffling. Pyd has hitherto relied on this behavior to implement its default argument support, and I only recently had this issue bite me in the ass. The following does not work: void function(int, char[]) fn = &foo; fn(); And yet, these templates almost seem to trick it into working. Is this a compiler check that is preventing possible runtime behavior? (A check that my template wackiness has somehow gotten around?)Kirk McDonald wrote:Then why does it work when I comment out line 28?I'm having some trouble with a very odd template problem. Take the following code: [test.d] import std.stdio; import ftype; // Daniel Keep's ftype module // A function with default arguments void foo(int i=20, char[] s="Monkey") { writefln("foo: %s %s", i, s); } // A function with the same arguments and no defaults void bar(int i, char[] s) { writefln("bar: %s %s", i, s); } // A function that takes a function pointer and the minimum // number of arguments the function can be called with, and // calls it. void Baz(fn_t, uint MIN_ARGS)(fn_t fn) { static if (MIN_ARGS == 0) fn();MIN_ARGS is 0 for 'foo', because thats what the NumberOfArgs template returns, using the function *alias*. the *type* doesnt tell the compiler that it can be called with no args. thats just a func type that takes two args. thus the error.-- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wikielse static if (MIN_ARGS == 1) fn(10); else static if (MIN_ARGS == 2) fn(15, "Copper"); } // A template function that takes a function alias and the // minimum number of args it can be called with, and calls // Baz void Blah(alias Fn, uint MIN_ARGS = NumberOfArgs!(typeof(&Fn))) () { alias typeof(&Fn) fn_t; fn_t fn = &Fn; Baz!(fn_t, MIN_ARGS)(fn); } void main() { Blah!(bar); // Line 28 Blah!(foo, 0); // Line 29 } $ build test test.d(14): Error: expected 2 arguments, not 0 test.d(24): template instance test22.Baz!(void(*)(int i, char[] s),0u) error instantiating test.d(29): template instance test22.Blah!(foo,0) error instantiating Curiously, this works if I comment out line 28: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test foo: 20 Monkey It also works if I comment out line 29 instead: $ build test gcc test.o ftype.o -o test -m32 -lphobos -lpthread -lm $ ./test bar: 15 Copper But if both lines are there together, it fails.
Jul 08 2006
Kirk McDonald wrote:Kirk McDonald wrote:Thanks for correcting me and sorry for being dumb and answering too quickly. ( I was just about to receive a pizza so I was in a hurry, he.. he... ) Looks like a very bizarre bug to me... the simplified case behaves exactly the same: void foo(int i=20) { } void bar(int i) { } void main() { { alias typeof(&bar) fn_t; // comment it out and the error goes away } { alias typeof(&foo) fn_t; fn_t fn = &foo; fn(); } } That's funny... I'm can't stop thinking that I've reported a similar bug more than a year ago :o -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/Tom S wrote:Actually, I think I'm going to be really pedantic and correct you:Kirk McDonald wrote:Then why does it work when I comment out line 28?I'm having some trouble with a very odd template problem. Take the following code: [test.d] import std.stdio; import ftype; // Daniel Keep's ftype module // A function with default arguments void foo(int i=20, char[] s="Monkey") { writefln("foo: %s %s", i, s); } // A function with the same arguments and no defaults void bar(int i, char[] s) { writefln("bar: %s %s", i, s); } // A function that takes a function pointer and the minimum // number of arguments the function can be called with, and // calls it. void Baz(fn_t, uint MIN_ARGS)(fn_t fn) { static if (MIN_ARGS == 0) fn();MIN_ARGS is 0 for 'foo', because thats what the NumberOfArgs template returns, using the function *alias*. the *type* doesnt tell the compiler that it can be called with no args. thats just a func type that takes two args. thus the error.
Jul 08 2006
Kirk McDonald wrote:Kirk McDonald wrote:For what I see, a function pointer *does* know about default arguments. That doesn't change your point though. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DTom S wrote:Actually, I think I'm going to be really pedantic and correct you: MIN_ARGS is 0 for 'foo' because I explicitly told it to be (on line 29). NumberOfArgs would evaluate to 2, because it does indeed operate on the type of the function pointer, which doesn't know a thing about default arguments. If lines 28 and 29 instead read:Kirk McDonald wrote:Then why does it work when I comment out line 28?I'm having some trouble with a very odd template problem. Take the following code: [test.d] import std.stdio; import ftype; // Daniel Keep's ftype module // A function with default arguments void foo(int i=20, char[] s="Monkey") { writefln("foo: %s %s", i, s); } // A function with the same arguments and no defaults void bar(int i, char[] s) { writefln("bar: %s %s", i, s); } // A function that takes a function pointer and the minimum // number of arguments the function can be called with, and // calls it. void Baz(fn_t, uint MIN_ARGS)(fn_t fn) { static if (MIN_ARGS == 0) fn();MIN_ARGS is 0 for 'foo', because thats what the NumberOfArgs template returns, using the function *alias*. the *type* doesnt tell the compiler that it can be called with no args. thats just a func type that takes two args. thus the error.
Jul 09 2006