Hi there,
back in the discussions about C++-"concepts" it was argued that
D-template-parameter constraints allow you to achieve the same goal.
Now, I find it fairly difficult to come up with a clean solution for
this that actually scales up for complex libraries. My best attempt so
far is as follows:
===================================================
template verifyMyConcept(A) {
static assert(is(A.type));
static assert(A.len >= 0);
static assert(is(typeof(A.init[0]) == A.type));
}
struct MyClass(T,int R) {
alias T type;
enum len = R;
T[R] value;
T opIndex(int idx) {
return value[idx];
}
mixin verifyMyConcept!(typeof(this));
}
void myfunction(A)(A arr)
if(__traits(compiles, verifyMyConcept!(A)))
{
}
unittest {
MyClass!(int,4) x;
mixin verifyMyConcept!(typeof(x));
myfunction(x);
}
===================================================
As you can see, this approach attempts to define all the requirements
for MyConcept in one place as individual static assertions. This permits
error messages to identify which requirement for the concept is not met.
Still the code seems fairly ugly to me and the error message is not
quite clear enough for my taste.
Ideally, there should be a way to use "concepts" similar to interfaces:
a) A concept should be defined readably in one place, listing a set of
requirements, possibly inheriting other concepts.
b) A struct implementing the concept should state this in a similar way
to a class that implements an interface.
c) A template that requires a parameter to fulfil a concept should state
this in a similar way to a function requiring a specific input type
and most importantly:
d) a user of the library should get a clear and simple error message
when using templates with parameters that do not fulfil the required
concept.
Has anyone achieved these goals better than my feeble attempt?
Greetings,
Norbert