Search code examples
templatesd

functions/delegates not matching overloaded template


It looks like D has problems picking the right overloaded template when passing functions and delegates to them. Take this example:

import std.stdio;

void test()(string a){
    writeln(a);
}

void test(Ret, Args...)(Ret function(Args) fn){
    writeln(fn(1, 2));
}

void test(T)(T a){
    assert(0);
}

void main(){
    test("something");
    test((int a, double b){
        return "works";
    });
}

Theoretically, this should print something\nworks. But this is the output:

something
[email protected](15): Assertion failure
...

It works when removing void test(T)(T a).

  1. Why is (T a) the selected match?
  2. Is there a way to force the right selection without passing the parameters explicitly, and without calling (Ret function(Args)) from within (T a)?

Solution

  • From the template specialization docs:

    If both a template with a sequence parameter and a template without a sequence parameter exactly match a template instantiation, the template without a TemplateSequenceParameter is selected.

    You can work around it by adding a constraint with isSomeFunction:

    void test(T)(T a) if (!isSomeFunction!T) {
        assert(0);
    }