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.container.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 pure nothrow @safe @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);
Ixs ixs;
ixs.length = 42;
import std.algorithm.mutation : move;
auto s = S(Lang.en, "alpha", move(ixs)); /+ TODO: use generic `makeOfLength` +/
import core.lifetime : move;
ia ~= move(s);
assert(ia.length == 2);
Instantiator for TypesafelyIndexed.