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

Reply via email to