Template Constraints and Variadic Templates
25.1 Template Constraints
Constraints pick overloads and give clearer errors. Use static assert inside for custom messages.
import std.traits, std.range;
T sumAll(T)(T[] arr) if (isNumeric!T)
{
T total = 0;
foreach (x; arr) total += x;
return total;
}
auto firstOrDefault(R)(R r, ElementType!R def) if (isInputRange!R)
{
return r.empty ? def : r.front;
}
void process(T)(T x)
if (is(typeof(x.serialize()) : string)) // structural constraint: "has serialize() returning string"
{
}25.2 Variadic Templates and AliasSeq
import std.meta;
void printAll(Args...)(Args args)
{
foreach (i, arg; args) // unrolled at compile time
writefln("%d: %s (%s)", i, arg, typeof(arg).stringof);
}
printAll(1, "two", 3.0);
alias Types = AliasSeq!(int, string, double);
alias Numbers = Filter!(isNumeric, Types); // (int, double)
alias Ptrs = staticMap!(Ptr, Types);
static assert(staticIndexOf!(string, Types) == 1);
enum allInts = allSatisfy!(isIntegral, int, long);
auto tupleSum(T...)(T args) { typeof(args[0]) s = 0; foreach (a; args) s += a; return s; }25.3 is Expressions
static if (is(T == int)) {} // exact type
static if (is(T : long)) {} // implicitly convertible
static if (is(T == U[], U)) {} // pattern match: T is an array of some U
static if (is(T == class)) {} // kind: class, struct, interface, enum, union, function, delegate
static if (is(typeof(T.init.foo()))) {} // does this expression compile?
static if (is(T : Base)) {}
static if (__traits(compiles, x.foo())) {}