Strange template problem
Kirk McDonald
kirklin.mcdonald at gmail.com
Sat Jul 8 14:10:33 PDT 2006
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
More information about the Digitalmars-d
mailing list