[Issue 3646] Default values of function arguments are ignored when instantiating a template.

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sun Jul 3 08:47:21 PDT 2011


http://d.puremagic.com/issues/show_bug.cgi?id=3646



--- Comment #7 from Stewart Gordon <smjg at iname.com> 2011-07-03 08:42:20 PDT ---
(In reply to comment #1)
> Not lets see how foo!(bar) looks like after a rewrite:
> 
> void foo(Fn)(Fn fn)
> {
>     fn(22);
> }

Actually, before this rewrite comes substituting in the template argument.

    void fooInstance(void function(int = 22) fn)
    {
        fn();
    }

which then becomes

    void fooInstance(void function(int) fn)
    {
        fn(22);
    }

> Now there is no wonder why dmd behaves like this.

But it makes sense only if there are actually two template instances involved. 
The essence of the bug is that, after it has instantiated foo with argument
void function(int = 22), the compiler matches any attempt to instantiate foo
with a void function(int), with or without a default argument, to this
instance.

(In reply to comment #2)
> Yeah, that was pretty much what I was thinking about.  The issue 
> cuts down to a question, should Foo be instantiated once or are the 
> function types equal?  For binary size and efficiency purposes I 
> agree that there should be one instantiation.  On the other hand 
> for meta programming and code generation which is what I am doing I 
> would like to have them as separate types, as I don't want to loose 
> this information.  Walter or Andrei would probably have to comment 
> on this issue.

But this seems to me a rare use case.  And you can do it with an alias template
parameter, though this does create a separate instance for each function name:
----------
import std.stdio;

void foo(alias fn)() {
    fn();
    fn(42);
}

void bar(int i = 22) {
    writefln("bar %d", i);
}
void bam(int i) {
    writefln("bam %d", i);
}
void quux() {
    writefln("quux");
}
void quux(int i) {
    writefln("quux %d", i);
}

void main() {
    foo!(bar)();    // works
    //foo!(bam)();  // correctly triggers compiler error (1.068 Win32)
    foo!(quux)();   // works with overloads as well
}
----------

I can see three possible ways to resolve this issue:

(a) Default arguments aren't part of the function type.  Then only one template
instance exists: foo!(void function(int)).  The template instance is then
illegal, since it tries to call a void function(int) with no arguments.

(b) Default arguments are part of the function type.  Then there are two
template instances: 
    foo(&bar) is foo!(void function(int = 22))
    foo(&bam) is foo!(void function(int))

Then foo(&bar) is legal: foo(&bar)() calls bar(22)
 and foo(&bam) is illegal

(c) Default arguments are part of the function type, but can be optimised away.
 Essentially, we detect while instantiating the template whether the template
body makes use of a default argument.  If so, create a separate instance for
each default argument or absence thereof.  Otherwise, create only one instance.
 Not sure whether this is desirable.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list