Walter Bright>I don't see that in the example given.<

I can try with one real example from my dlibs1. This template is the third I 
use with foreach to create the fake static foreach, this accepts a step 
(stride) value too.

But such step can't be zero, so I add a static assert inside it to make sure 
you don't try to instantiate it with a step = 0.


template Range(int start, int stop, int step) {
    static assert(step != 0, "Range: step must be != 0");

    static if (step > 0) {
        static if (stop <= start)
            alias Tuple!() Range;
        else
            alias Tuple!(Range!(start, stop-step, step), stop-step) Range;
    } else {
        static if (stop >= start)
            alias Tuple!() Range;
        else
            alias Tuple!(Range!(start, stop-step, step), stop-step) Range;
    }
}


In D2 I can use a template constraint instead of a static assert here (this is 
sometimes bad, because you lose the error text message given by the static 
assert, that in complex situations can be useful):

template Range(int start, int stop, int step) if (step != 0) {


Now that Range needs unittests, things like this that test that Range gives the 
right output:

unittest { // Tests of Range!()
    int[] a;
    foreach (n; Range!(0, 10, 2))
        a ~= n;
    assert(a == [0, 2, 4, 6, 8]);
}


But the "specs" of the Range template say that Range must not work if step is 
zero (this means that the unittest has to fail if Range compiles when the given 
step is zero). So I have to test this too. I can do that with one more unittest 
(D1 code):

    static assert(!is(typeof( Range!(15, 3, 0) )));

In D2 I can use the __traits:

    static assert(!__traits(compiles, Range!(15, 3, 0) ));

Hope this helps.

Bye,
bearophile

Reply via email to