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).