Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
July 08, 2006 Strange template problem | ||||
---|---|---|---|---|
| ||||
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
|
July 08, 2006 Re: Strange template problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | 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 +/ |
July 08, 2006 Re: Strange template problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom S | Tom S wrote: > 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. Then why does it work when I comment out line 28? > > >> 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 |
July 08, 2006 Re: Strange template problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote: > Tom S wrote: > >> 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. > > > Then why does it work when I comment out line 28? 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?) > >> >> >>> 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 |
July 08, 2006 Re: Strange template problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote: > Kirk McDonald wrote: >> Tom S wrote: >> >>> 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. >> >> >> Then why does it work when I comment out line 28? > > Actually, I think I'm going to be really pedantic and correct you: 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 +/ |
July 09, 2006 Re: Strange template problem | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote: > Kirk McDonald wrote: >> Tom S wrote: >> >>> 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. >> >> >> Then why does it work when I comment out line 28? > > 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: > 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#D |
Copyright © 1999-2021 by the D Language Foundation