std.range.primitives

This module is a submodule of std.range.

It defines the bidirectional and forward range primitives for arrays: empty, front, back, popFront, popBack and save.

It provides basic range functionality by defining several templates for testing whether a given object is a range, and what kind of range it is:

isInputRangeTests if something is an input range, defined to be something from which one can sequentially read data using the primitives front, popFront, and empty.
isOutputRangeTests if something is an output range, defined to be something to which one can sequentially write data using the put primitive.
isForwardRangeTests if something is a forward range, defined to be an input range with the additional capability that one can save one's current position with the save primitive, thus allowing one to iterate over the same range multiple times.
isBidirectionalRangeTests if something is a bidirectional range, that is, a forward range that allows reverse traversal using the primitives back and popBack.
isRandomAccessRangeTests if something is a random access range, which is a bidirectional range that also supports the array subscripting operation via the primitive opIndex.

It also provides number of templates that test for various range capabilities:

hasMobileElementsTests if a given range's elements can be moved around using the primitives moveFront, moveBack, or moveAt.
ElementTypeReturns the element type of a given range.
ElementEncodingTypeReturns the encoding element type of a given range.
hasSwappableElementsTests if a range is a forward range with swappable elements.
hasAssignableElementsTests if a range is a forward range with mutable elements.
hasLvalueElementsTests if a range is a forward range with elements that can be passed by reference and have their address taken.
hasLengthTests if a given range has the length attribute.
isInfiniteTests if a given range is an infinite range.
hasSlicingTests if a given range supports the array slicing operation R[x .. y].

Finally, it includes some convenience functions for manipulating ranges:

popFrontNAdvances a given range by up to n elements.
popBackNAdvances a given bidirectional range from the right by up to n elements.
popFrontExactlyAdvances a given range by up exactly n elements.
popBackExactlyAdvances a given bidirectional range from the right by exactly n elements.
moveFrontRemoves the front element of a range.
moveBackRemoves the back element of a bidirectional range.
moveAtRemoves the i'th element of a random-access range.
walkLengthComputes the length of any range in O(n) time.
putOutputs element e to a range.

Members

Functions

moveAt
ElementType!R moveAt(R r, size_t i)

Moves element at index i of r out and returns it. Leaves r[i] in a destroyable state that does not allocate any resources (usually equal to its .init value).

moveBack
ElementType!R moveBack(R r)

Moves the back of r out and returns it. Leaves r.back in a destroyable state that does not allocate any resources (usually equal to its .init value).

moveFront
ElementType!R moveFront(R r)

Moves the front of r out and returns it.

popBack
void popBack(inout(T)[] a)

Implements the range interface primitive popBack for built-in arrays. Due to the fact that nonmember functions can be called with the first argument using the dot notation, array.popBack is equivalent to popBack(array). For narrow strings, popFront automatically eliminates the last code point.

popBackExactly
void popBackExactly(Range r, size_t n)

Eagerly advances r itself (not a copy) exactly n times (by calling r.popFront). popFrontExactly takes r by ref, so it mutates the original range. Completes in O(1) steps for ranges that support slicing, and have either length or are infinite. Completes in O(n) time for all other ranges.

popBackN
size_t popBackN(Range r, size_t n)

popFrontN eagerly advances r itself (not a copy) up to n times (by calling r.popFront). popFrontN takes r by ref, so it mutates the original range. Completes in O(1) steps for ranges that support slicing and have length. Completes in O(n) time for all other ranges.

popFront
void popFront(inout(T)[] a)
void popFront(inout(C)[] str)

Implements the range interface primitive popFront for built-in arrays. Due to the fact that nonmember functions can be called with the first argument using the dot notation, array.popFront is equivalent to popFront(array). For narrow strings, popFront automatically advances to the next code point.

popFrontExactly
void popFrontExactly(Range r, size_t n)

Eagerly advances r itself (not a copy) exactly n times (by calling r.popFront). popFrontExactly takes r by ref, so it mutates the original range. Completes in O(1) steps for ranges that support slicing, and have either length or are infinite. Completes in O(n) time for all other ranges.

popFrontN
size_t popFrontN(Range r, size_t n)

popFrontN eagerly advances r itself (not a copy) up to n times (by calling r.popFront). popFrontN takes r by ref, so it mutates the original range. Completes in O(1) steps for ranges that support slicing and have length. Completes in O(n) time for all other ranges.

put
void put(R r, E e)

Outputs e to r. The exact effect is dependent upon the two types. Several cases are accepted, as described below. The code snippets are attempted in order, and the first to compile "wins" and gets evaluated.

walkLength
auto walkLength(Range range)
auto walkLength(Range range, size_t upTo)

This is a best-effort implementation of length for any kind of range.

Manifest constants

autodecodeStrings
enum autodecodeStrings;

Properties

back
dchar back [@property getter]

Implements the range interface primitive back for built-in arrays. Due to the fact that nonmember functions can be called with the first argument using the dot notation, array.back is equivalent to back(array). For narrow strings, back automatically returns the last code point as a dchar.

back
inout(T) back [@property getter]

Implements the range interface primitive back for built-in arrays. Due to the fact that nonmember functions can be called with the first argument using the dot notation, array.back is equivalent to back(array). For narrow strings, back automatically returns the last code point as a dchar.

empty
bool empty [@property getter]

Implements the range interface primitive empty for types that obey hasLength property and for narrow strings. Due to the fact that nonmember functions can be called with the first argument using the dot notation, a.empty is equivalent to empty(a).

front
inout(T) front [@property getter]
dchar front [@property getter]

Implements the range interface primitive front for built-in arrays. Due to the fact that nonmember functions can be called with the first argument using the dot notation, array.front is equivalent to front(array). For narrow strings, front automatically returns the first code point as a dchar.

save
inout(T)[] save [@property getter]

Implements the range interface primitive save for built-in arrays. Due to the fact that nonmember functions can be called with the first argument using the dot notation, array.save is equivalent to save(array). The function does not duplicate the content of the array, it simply returns its argument.

Templates

ElementEncodingType
template ElementEncodingType(R)

The encoding element type of R. For narrow strings (char[], wchar[] and their qualified variants including string and wstring), ElementEncodingType is the character type of the string. For all other types, ElementEncodingType is the same as ElementType.

ElementType
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.

hasLength
template hasLength(R)

Yields true if R has a length member that returns a value of size_t type. R does not have to be a range. If R is a range, algorithms in the standard library are only guaranteed to support length with type size_t.

hasSwappableElements
template hasSwappableElements(R)

Returns true if R is an input range and has swappable elements. The following code should compile for any range with swappable elements.

isInfinite
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:

Variables

hasAssignableElements
enum bool hasAssignableElements(R);

Returns true if R is an input range and has mutable elements. The following code should compile for any range with assignable elements.

hasLvalueElements
enum bool hasLvalueElements(R);

Tests whether the range R has lvalue elements. These are defined as elements that can be passed by reference and have their address taken. The following code should compile for any range with lvalue elements.

hasMobileElements
enum bool hasMobileElements(R);

Returns true iff R is an input range that supports the moveFront primitive, as well as moveBack and moveAt if it's a bidirectional or random access range. These may be explicitly implemented, or may work via the default behavior of the module level functions moveFront and friends. The following code should compile for any range with mobile elements.

hasSlicing
enum bool hasSlicing(R);

Returns true if R offers a slicing operator with integral boundaries that returns a forward range type.

isBidirectionalRange
enum bool isBidirectionalRange(R, E);

Returns true if R is a forward range. A forward range is an input range r that can save "checkpoints" by saving r.save to another value of type R. Notable examples of input ranges that are not forward ranges are file/socket ranges; copying such a range will not save the position in the stream, and they most likely reuse an internal buffer as the entire stream does not sit in memory. Subsequently, advancing either the original or the copy will advance the stream, so the copies are not independent.

isForwardRange
enum bool isForwardRange(R);
enum bool isForwardRange(R, E);

Returns true if R is a forward range. A forward range is an input range r that can save "checkpoints" by saving r.save to another value of type R. Notable examples of input ranges that are not forward ranges are file/socket ranges; copying such a range will not save the position in the stream, and they most likely reuse an internal buffer as the entire stream does not sit in memory. Subsequently, advancing either the original or the copy will advance the stream, so the copies are not independent.

isInputRange
enum bool isInputRange(R, E);

ditto

isOutputRange
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 put(r, e) as defined above.

isRandomAccessRange
enum bool isRandomAccessRange(R);
enum bool isRandomAccessRange(R, E);

Returns true if R is a random-access range. A random-access range is a bidirectional range that also offers the primitive opIndex, OR an infinite forward range that offers opIndex. In either case, the range must either offer length or be infinite. The following code should compile for any random-access range.

Meta

Authors

Andrei Alexandrescu, David Simcha, and Jonathan M Davis. Credit for some of the ideas in building this module goes to Leonardo Maffi.