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.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);

Meta