[Issue 4085] Steps toward a static foreach

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sun Jun 6 07:09:46 PDT 2010


http://d.puremagic.com/issues/show_bug.cgi?id=4085



--- Comment #1 from bearophile_hugs at eml.cc 2010-06-06 07:09:44 PDT ---
// Until bug 4085 gets fixed, I use something similar to this.
// I suggest to not add this to Phobos because it
//   will become useless when bug 4085 is partially of fully fixed.



import std.typetuple: TypeTuple;
import std.traits: isArray;

version(unittest) {
    import std.string: split; // for arrayToTypeTuple!() unittests
}

/****************************************
Converts at compile time an enum array into a TypeTuple that
contains the same items.

Example:
--------
foreach (i; arrayToTypeTuple!([1, 2]))
    static assert(i > 0);
--------
*/
template arrayToTypeTuple(alias items) {
    static assert (isArray!(typeof(items)));
    static if (items == null || items.length == 0) // bug 4284
        alias TypeTuple!() arrayToTypeTuple;
    else
        alias TypeTuple!(items[0], arrayToTypeTuple!(items[1..$]))
arrayToTypeTuple;
}

unittest { // Tests of arrayToTypeTuple!()
    string[] items;
    foreach (s; arrayToTypeTuple!(split(""))) {
        static assert(s.length > 0);
        items ~= s;
    }
    assert(items.length == 0);

    items.length = 0;
    foreach (s; arrayToTypeTuple!(split("foo"))) {
        static assert(s.length > 0);
        items ~= s;
    }
    assert(items == ["foo"]);

    items.length = 0;
    foreach (s; arrayToTypeTuple!(split("foo bar red"))) {
        static assert(s.length > 0);
        items ~= s;
    }
    assert(items == ["foo", "bar", "red"]);

    foreach (i; arrayToTypeTuple!([1, 2]))
        static assert(i > 0);
} // End tests of arrayToTypeTuple!()



/****************************************
Template, similar to iota(), but generates a tuple at compile time.

Useful for "static foreach" loops, where range extrema are compile time
constants:
-----------
foreach (i; Iota!(3))
    a[i] = b[i];

// becomes unrolled and compiled as:
    a[0] = b[0];
    a[1] = b[1];
    a[2] = b[2];
-----------
*/
template Iota(int stop) {
    static if (stop <= 0)
        alias TypeTuple!() Iota;
    else
        alias TypeTuple!(Iota!(stop-1), stop-1) Iota;
}

/// ditto
template Iota(int start, int stop) {
    static if (stop <= start)
        alias TypeTuple!() Iota;
    else
        alias TypeTuple!(Iota!(start, stop-1), stop-1) Iota;
}

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

    static if (step > 0) {
        static if (stop <= start)
            alias TypeTuple!() Iota;
        else
            alias TypeTuple!(Iota!(start, stop-step, step), stop-step) Iota;
    } else {
        static if (stop >= start)
            alias TypeTuple!() Iota;
        else
            alias TypeTuple!(Iota!(start, stop-step, step), stop-step) Iota;
    }
} // End Iota!(a,b,c)

unittest { // Tests of Iota!()
    static assert(Iota!(0).length == 0);

    int[] a;

    foreach (n; Iota!(5))
        a ~= n;
    assert(a == [0, 1, 2, 3, 4]);

    a.length = 0;
    foreach (n; Iota!(-5))
        a ~= n;
    assert(a == new int[0]);

    a.length = 0;
    foreach (n; Iota!(4, 7))
        a ~= n;
    assert(a == [4, 5, 6]);

    a.length = 0;
    foreach (n; Iota!(-1, 4))
        a ~= n;
    static assert(Iota!(-1, 4).length == 5);
    assert(a == [-1, 0, 1, 2, 3]);

    a.length = 0;
    foreach (n; Iota!(4, 2))
        a ~= n;
    assert(a == new int[0]);

    a.length = 0;
    foreach (n; Iota!(0, 10, 2))
        a ~= n;
    assert(a == [0, 2, 4, 6, 8]);

    a.length = 0;
    foreach (n; Iota!(3, 15, 3))
        a ~= n;
    assert(a == [3, 6, 9, 12]);

    a.length = 0;
    foreach (n; Iota!(15, 3, 1))
        a ~= n;
    assert(a == new int[0]);

    a.length = 0;
    foreach (n; Iota!(10, 0, -1))
        a ~= n;
    assert(a == [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);

    a.length = 0;
    foreach (n; Iota!(15, 3, -2))
        a ~= n;
    assert(a == [15, 13, 11, 9, 7, 5]);

    static assert(!is(typeof( Iota!(15, 3, 0) ))); // stride = 0 statically
asserts
} // End tests of Iota!()


void main() {}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list