I have a few cases where I would like to pass in a function as a value to a template, but I want to ensure that the function takes certain kinds of parameters, is a const function, or matches any other set of conditions.

What is the best way to do this? Just to avoid any potential confusion, I've included a few examples below. I'm using explicit functions rather than lambdas just avoid any possibility of types being incorrectly inferred.

size_t myHashFunction(int a) { return cast(size_t) a; }

void main() {
    class A(KeyT, HashF) { }
    auto a = new A!(int, myHashFunction);
// ^ onlineapp.d: Error: template instance `A!(int, myHashFunction)`
    // does not match template declaration `A(KeyT, HashF)`

// Alias parameter: https://dlang.org/spec/template.html#aliasparameters
    class B(KeyT, alias HashF) { }
    auto b = new B!(int, myHashFunction);
// ^ Works, but we cannot enforce the kind of function passed in.

// Typed alias parameter: https://dlang.org/spec/template.html#typed_alias_op
    class C(KeyT, alias size_t function(KeyT) HashF) { }
    auto c = new C!(int, myHashFunction);
// ^ onlineapp.d: Error: template instance `C!(int, myHashFunction)` // does not match template declaration `C(KeyT, alias size_t function(KeyT) HashF)`

// Specialization: https://dlang.org/spec/template.html#alias_parameter_specialization
    class D(KeyT, alias HashF : size_t function(KeyT)) { }
    auto d = new D!(int, myHashFunction
// ^ onlineapp.d: Error: template instance `D!(int, myHashFunction)` // does not match template declaration `D(KeyT, alias HashF : size_t function(KeyT))`
}

Looking at some of the code in std.algorithm, it seem that static asserts are sometimes used for this purpose. Does anyone have a solution to this problem of instantiating template classes whose parameters are functions? I have used std.function "unaryFun" before, but this has the problem of not being able to specify function attributes, like const.

Reply via email to