On Saturday, 13 May 2017 at 14:41:50 UTC, Stanislav Blinov wrote:
template types(args...) {
   static if (args.length)
alias types = AliasSeq!(typeof(args[0]), types!(args[1..$]));
   else
       alias types = AliasSeq!();
}
...
   foreach(i, T; types!args) {

typeof(args) ;-)

       static if (is(T == string)) {
pragma(msg, format!"Argument %d is a string, which is not supported"
                   (i+1));

The problem with this approach is all the work required to convert existing code to use this style. Breaking the binary ops of the constraint into parts and reporting which failed (as the other replies mention) already would work with existing code, even if your approach can allow better messages. The binary ops part would immediately bring a huge improvement, despite any deficiencies.

There are other alternatives, e.g. there's a DIP by Kenji Hara:

https://wiki.dlang.org/User:9rnsr/DIP:_Template_Parameter_Constraint

The approach I'm proposing is more flexible though, as it would allow to evaluate all arguments as a unit and infer more information (e.g. __traits(isRef, args[i]). Constraint on every argument won't allow the latter, and would potentially require writing more explicit overloads.

I think we should allow inline constraints*, non-inline constraints can still be used/combined. Inline constraints are easier to read and relate to what they affect, allowing any non-inline constraint to be considered as something with a wider scope (i.e., multiple arguments).

* template foo(R if isInputRange)

A side benefit is enum/alias/variable templates, they don't currently allow constraints in the grammar - they could have inline constraints without harming readability (presumably why constraints aren't supported).

Reply via email to