Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.primitives

Templates used to check primitives and range primitives for arrays with multi-dimensional like API support.

Note UTF strings behaves like common arrays in Mir. std.uni.byCodePoint can be used to create a range of characters.

License:
Authors:
Ilya Yaroshenko, Andrei Alexandrescu, David Simcha, and Jonathan M Davis. Credit for some of the ideas in building this module goes to Leonardo Maffi
enum bool hasLength(R);
Returns:
true if R has a length member that returns an integral type implicitly convertible to size_t.
R does not have to be a range.
Examples:
static assert(hasLength!(char[]));
static assert(hasLength!(int[]));
static assert(hasLength!(inout(int)[]));

struct B { size_t length() const { return 0; } }
struct C { @property size_t length() const { return 0; } }
static assert(hasLength!(B));
static assert(hasLength!(C));
enum bool hasShape(R);
Returns:
true if R has a shape member that returns an static array type of size_t[N].
Examples:
static assert(hasShape!(char[]));
static assert(hasShape!(int[]));
static assert(hasShape!(inout(int)[]));

struct B { size_t length() const { return 0; } }
struct C { @property size_t length() const { return 0; } }
static assert(hasShape!(B));
static assert(hasShape!(C));
@property auto shape(Range)(auto ref scope const Range range)
if (hasLength!Range || hasShape!Range);
Examples:
static assert([2, 2, 2].shape == [3]);
template DimensionCount(T)
enum size_t DimensionCount;
Extracts dimension count from a Slice. Alias for isSlice.
@property bool anyEmpty(Range)(auto ref scope const Range range)
if (hasShape!Range || __traits(hasMember, Range, "anyEmpty"));
@property size_t elementCount(Range)(auto ref scope const Range range)
if (hasShape!Range || __traits(hasMember, Range, "elementCount"));
template DeepElementType(S) if (is(S == struct) || is(S == class) || is(S == interface))

template DeepElementType(S : T[], T)
Returns the element type of a struct with .DeepElement inner alias or a type of common array. Returns ForeachType if struct does not have .DeepElement member.
bool empty(size_t dim = 0, T)(scope const T[] ar)
if (!dim);
Examples:
assert((int[]).init.empty);
assert(![1].empty!0); // Slice-like API
ref inout(T) front(size_t dim = 0, T)(return scope inout(T)[] ar)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
assert(*&[3, 4].front == 3); // access be ref
assert([3, 4].front!0 == 3); // Slice-like API
ref inout(T) back(size_t dim = 0, T)(return scope inout(T)[] ar)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
assert(*&[3, 4].back == 4); // access be ref
assert([3, 4].back!0 == 4); // Slice-like API
void popFront(size_t dim = 0, T)(ref scope inout(T)[] ar)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
auto ar = [3, 4];
ar.popFront;
assert(ar == [4]);
ar.popFront!0;  // Slice-like API
assert(ar == []);
void popBack(size_t dim = 0, T)(ref scope inout(T)[] ar)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
auto ar = [3, 4];
ar.popBack;
assert(ar == [3]);
ar.popBack!0;  // Slice-like API
assert(ar == []);
size_t popFrontN(size_t dim = 0, T)(ref scope inout(T)[] ar, size_t n)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
auto ar = [3, 4];
ar.popFrontN(1);
assert(ar == [4]);
ar.popFrontN!0(10);  // Slice-like API
assert(ar == []);
size_t popBackN(size_t dim = 0, T)(ref scope inout(T)[] ar, size_t n)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
auto ar = [3, 4];
ar.popBackN(1);
assert(ar == [3]);
ar.popBackN!0(10);  // Slice-like API
assert(ar == []);
void popFrontExactly(size_t dim = 0, T)(ref scope inout(T)[] ar, size_t n)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
auto ar = [3, 4, 5];
ar.popFrontExactly(2);
assert(ar == [5]);
ar.popFrontExactly!0(1);  // Slice-like API
assert(ar == []);
void popBackExactly(size_t dim = 0, T)(ref scope inout(T)[] ar, size_t n)
if (!dim && !is(Unqual!T[] == void[]));
Examples:
auto ar = [3, 4, 5];
ar.popBackExactly(2);
assert(ar == [3]);
ar.popBackExactly!0(1);  // Slice-like API
assert(ar == []);
size_t length(size_t d : 0, T)(in T[] array)
if (d == 0);
Examples:
assert([1, 2].length!0 == 2);
assert([1, 2].elementCount == 2);
inout(T)[] save(T)(return scope inout(T)[] array);
Examples:
auto a = [1, 2];
assert(a is a.save);
enum bool isInputRange(R);
Returns true if R is an input range. An input range must define the primitives empty, popFront, and front. The following code should compile for any input range.
R r;              // can define a range object
if (r.empty) {}   // can test for empty
r.popFront();     // can invoke popFront()
auto h = r.front; // can get the front of the range of non-void type
The following are rules of input ranges are assumed to hold true in all Phobos code. These rules are not checkable at compile-time, so not conforming to these rules when writing ranges or range based code will result in undefined behavior.
  • r.empty returns false if and only if there is more data available in the range.
  • r.empty evaluated multiple times, without calling r.popFront, or otherwise mutating the range object or the underlying data, yields the same result for every evaluation.
  • r.front returns the current element in the range. It may return by value or by reference.
  • r.front can be legally evaluated if and only if evaluating r.empty has, or would have, equaled false.
  • r.front evaluated multiple times, without calling r.popFront, or otherwise mutating the range object or the underlying data, yields the same result for every evaluation.
  • r.popFront advances to the next element in the range.
  • r.popFront can be called if and only if evaluating r.empty has, or would have, equaled false.
Also, note that Phobos code assumes that the primitives r.front and r.empty are Ο(1) time complexity wise or "cheap" in terms of running time. Ο() statements in the documentation of range functions are made with this assumption.
Parameters:
R type to be tested
Returns:
true if R is an input range, false if not
template isInfinite(R)
Returns true if R is an infinite input range. An infinite input range is an input range that has a statically-defined enumerated member called empty that is always false, for example:
struct MyInfiniteRange
{
    enum bool empty = false;
    ...
}
template ElementType(R)
The element type of R. R does not have to be a range. The element type is determined as the type yielded by r.front for an object r of type R. For example, ElementType!(T[]) is T if T[] isn't a narrow string; if it is, the element type is dchar. If R doesn't have front, ElementType!R is void.
auto walkLength(Range)(Range range)
if (isIterable!Range && !isInfinite!Range);
This is a best-effort implementation of length for any kind of range. If hasLength!Range, simply returns range.length without checking upTo (when specified). Otherwise, walks the range through its length and returns the number of elements seen. Performes Ο(n) evaluations of range.empty and range.popFront(), where n is the effective length of range.
enum bool isOutputRange(R, E);
Returns true if R is an output range for elements of type E. An output range is defined functionally as a range that supports the operation r.put(e).