strictlyIndexed

Instantiator for TypesafelyIndexed.

strictlyIndexed
(
R
)
()

Examples

enum m = 3;
int[m] x = [11, 22, 33];
auto y = x.strictlyIndexed;

alias Y = typeof(y);

static assert(is(typeof(y.findIndex(11).index) == Y.Index));

assert(y.findIndex(11).exists);
assert(y.findIndex(22).exists);
assert(y.findIndex(33).exists);

if (auto hit = y.findIndex(11)) { assert(hit.index == 0); } else { assert(false); }
if (auto hit = y.findIndex(22)) { assert(hit.index == 1); } else { assert(false); }
if (auto hit = y.findIndex(33)) { assert(hit.index == 2); } else { assert(false); }

assert(!y.findIndex(44));
assert(!y.findIndex(55));

assert(!y.findIndex(44).exists);
assert(!y.findIndex(55).exists);
enum N = 7;
alias T = TypesafelyIndexed!(size_t[N]); // static array
static assert(T.sizeof == N*size_t.sizeof);
import nxt.modulo : Mod, mod;

T x;

x[Mod!N(1)] = 11;
x[1.mod!N] = 11;
assert(x[1.mod!N] == 11);

x.at!1 = 12;
static assert(!__traits(compiles, { x.at!N; }));
assert(x.at!1 == 12);
int[3] x = [1, 2, 3];

// sample index
struct Index(T = size_t)
    if (isUnsigned!T)
{
    this(T i) { this._i = i; }
    T opCast(U : T)() const { return _i; }
    private T _i = 0;
}
alias J = Index!size_t;

enum E { e0, e1, e2 }

with (E)
{
    auto xb = x.indexedBy!ubyte;
    auto xi = x.indexedBy!uint;
    auto xj = x.indexedBy!J;
    auto xe = x.indexedBy!E;
    auto xf = x.strictlyIndexed;

    auto xs = x.indexedBy!"I";
    alias XS = typeof(xs);
    XS xs_;

    // indexing with correct type
    xb[  0 ] = 11; assert(xb[  0 ] == 11);
    xi[  0 ] = 11; assert(xi[  0 ] == 11);
    xj[J(0)] = 11; assert(xj[J(0)] == 11);
    xe[ e0 ] = 11; assert(xe[ e0 ] == 11);

    // indexing with wrong type
    static assert(!__traits(compiles, { xb[J(0)] = 11; }));
    static assert(!__traits(compiles, { xi[J(0)] = 11; }));
    static assert(!__traits(compiles, { xj[  0 ] = 11; }));
    static assert(!__traits(compiles, { xe[  0 ] = 11; }));
    static assert(!__traits(compiles, { xs[  0 ] = 11; }));
    static assert(!__traits(compiles, { xs_[  0 ] = 11; }));

    import std.algorithm.comparison : equal;
    import std.algorithm.iteration : filter;

    assert(equal(xb[].filter!(a => a < 11), [2, 3]));
    assert(equal(xi[].filter!(a => a < 11), [2, 3]));
    assert(equal(xj[].filter!(a => a < 11), [2, 3]));
    assert(equal(xe[].filter!(a => a < 11), [2, 3]));
    // assert(equal(xs[].filter!(a => a < 11), [2, 3]));
}
auto x = [1, 2, 3];

// sample index
struct Index(T = size_t)
    if (isUnsigned!T)
{
    this(T ix) { this._ix = ix; }
    T opCast(U : T)() const { return _ix; }
    private T _ix = 0;
}
alias J = Index!size_t;

enum E { e0, e1, e2 }

with (E)
{
    auto xb = x.indexedBy!ubyte;
    auto xi = x.indexedBy!uint;
    auto xj = x.indexedBy!J;
    auto xe = x.indexedBy!E;

    // indexing with correct type
    xb[  0 ] = 11; assert(xb[  0 ] == 11);
    xi[  0 ] = 11; assert(xi[  0 ] == 11);
    xj[J(0)] = 11; assert(xj[J(0)] == 11);
    xe[ e0 ] = 11; assert(xe[ e0 ] == 11);

    // slicing with correct type
    xb[  0  ..   1 ] = 12; assert(xb[  0  ..   1 ] == [12]);
    xi[  0  ..   1 ] = 12; assert(xi[  0  ..   1 ] == [12]);
    xj[J(0) .. J(1)] = 12; assert(xj[J(0) .. J(1)] == [12]);
    xe[ e0  ..  e1 ] = 12; assert(xe[ e0  ..  e1 ] == [12]);

    // indexing with wrong type
    static assert(!__traits(compiles, { xb[J(0)] = 11; }));
    static assert(!__traits(compiles, { xi[J(0)] = 11; }));
    static assert(!__traits(compiles, { xj[  0 ] = 11; }));
    static assert(!__traits(compiles, { xe[  0 ] = 11; }));

    // slicing with wrong type
    static assert(!__traits(compiles, { xb[J(0) .. J(0)] = 11; }));
    static assert(!__traits(compiles, { xi[J(0) .. J(0)] = 11; }));
    static assert(!__traits(compiles, { xj[  0  ..   0 ] = 11; }));
    static assert(!__traits(compiles, { xe[  0  ..   0 ] = 11; }));

    import std.algorithm.comparison : equal;
    import std.algorithm.iteration : filter;

    assert(equal(xb.filter!(a => a < 11), [2, 3]));
    assert(equal(xi.filter!(a => a < 11), [2, 3]));
    assert(equal(xj.filter!(a => a < 11), [2, 3]));
    assert(equal(xe.filter!(a => a < 11), [2, 3]));
}
auto x = [1, 2, 3];
struct I(T = size_t)
{
    this(T ix) { this._ix = ix; }
    T opCast(U : T)() const { return _ix; }
    private T _ix = 0;
}
alias J = I!size_t;
auto xj = x.indexedBy!J;
auto x = [1, 2, 3];
struct I(T = size_t)
{
    private T _ix = 0;
}
alias J = I!size_t;
static assert(!__traits(compiles, { auto xj = x.indexedBy!J; }));
auto x = [1, 2, 3];
import nxt.bound : Bound;
alias B = Bound!(ubyte, 0, 2);
B b;
auto c = cast(size_t)b;
auto y = x.indexedBy!B;
import nxt.dynamic_array : Array = DynamicArray;

enum Lang { en, sv, fr }

alias Ixs = Array!int;

struct S
{
    Lang lang;
    string data;
    Ixs ixs;
}

alias A = Array!S;

struct I
{
    size_t opCast(U : size_t)() const @safe pure nothrow @nogc { return _ix; }
    uint _ix;
    alias _ix this;
}

I i;
static assert(isCastableTo!(I, size_t));
static assert(isIndexableBy!(A, I));

alias IA = IndexedBy!(A, I);
IA ia;
ia ~= S.init;
assert(ia.length == 1);
auto s = S(Lang.en, "alpha", Ixs.withLength(42));

import core.lifetime : move;

ia ~= move(s);
assert(ia.length == 2);

Meta