On Sunday, 23 December 2018 at 17:13:49 UTC, Vijay Nayar wrote:
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.
I assume you are looking for constraints...
https://dlang.org/concepts.html
Then, case B is the way to go, see
https://run.dlang.io/is/jWU3tr
Case D also looks promising. Not sure, how to formulate the
specialization right now...
There are a lot of traits you can use for the constraints.
https://dlang.org/phobos/std_traits.html
and
https://dlang.org/spec/traits.html
e.g., for constness there is getFunctionAttributes, which could
be useful.