RefRange

Wrapper which effectively makes it possible to pass a range by reference. Both the original range and the RefRange will always have the exact same elements. Any operation done on one will affect the other. So, for instance, if it's passed to a function which would implicitly copy the original range if it were passed to it, the original range is not copied but is consumed as if it were a reference type.

Note: save works as normal and operates on a new range, so if save is ever called on the RefRange, then no operations on the saved range will affect the original.

Constructors

this
this(R* range)

Members

Aliases

opDollar
alias opDollar = length

Only defined if hasLength!R is true.

Functions

moveAt
auto moveAt(size_t index)

Only defined if hasMobileElements!R and isRandomAccessRange!R are true.

moveBack
auto moveBack()

Only defined if hasMobileElements!R and isBidirectionalRange!R are true.

moveFront
auto moveFront()

Only defined if hasMobileElements!R and isForwardRange!R are true.

opAssign
auto opAssign(RefRange rhs)

This does not assign the pointer of rhs to this RefRange. Rather it assigns the range pointed to by rhs to the range pointed to by this RefRange. This is because any operation on a RefRange is the same is if it occurred to the original range. The one exception is when a RefRange is assigned null either directly or because rhs is null. In that case, RefRange no longer refers to the original range but is null.

opAssign
void opAssign(typeof(null) rhs)
opIndex
auto ref opIndex(IndexType index)

Only defined if isRandomAccessRange!R is true.

opSlice
auto opSlice()

Only defined if isForwardRange!R is true.

opSlice
auto opSlice(IndexType1 begin, IndexType2 end)

Only defined if hasSlicing!R is true.

popBack
void popBack()

Only defined if isBidirectionalRange!R is true.

popFront
void popFront()

Properties

back
auto back [@property getter]
ElementType!R back [@property setter]

Only defined if isBidirectionalRange!R is true.

front
auto front [@property getter]
ElementType!R front [@property setter]
length
size_t length [@property getter]

Only defined if hasLength!R is true.

ptr
inout(R*) ptr [@property getter]

A pointer to the wrapped range.

save
auto save [@property getter]

Only defined if isForwardRange!R is true.

Templates

isSafe (from std.traits)
template isSafe(alias func) via public import std.traits : isSafe;

true if func is @safe or @trusted.

Return Value

A RefRange. If the given range is a class type (and thus is already a reference type), then the original range is returned rather than a RefRange.

Examples

Basic Example

import std.algorithm.searching : find;
ubyte[] buffer = [1, 9, 45, 12, 22];
auto found1 = find(buffer, 45);
assert(found1 == [45, 12, 22]);
assert(buffer == [1, 9, 45, 12, 22]);

auto wrapped1 = refRange(&buffer);
auto found2 = find(wrapped1, 45);
assert(*found2.ptr == [45, 12, 22]);
assert(buffer == [45, 12, 22]);

auto found3 = find(wrapped1.save, 22);
assert(*found3.ptr == [22]);
assert(buffer == [45, 12, 22]);

string str = "hello world";
auto wrappedStr = refRange(&str);
assert(str.front == 'h');
str.popFrontN(5);
assert(str == " world");
assert(wrappedStr.front == ' ');
assert(*wrappedStr.ptr == " world");

opAssign Example.

ubyte[] buffer1 = [1, 2, 3, 4, 5];
ubyte[] buffer2 = [6, 7, 8, 9, 10];
auto wrapped1 = refRange(&buffer1);
auto wrapped2 = refRange(&buffer2);
assert(wrapped1.ptr is &buffer1);
assert(wrapped2.ptr is &buffer2);
assert(wrapped1.ptr !is wrapped2.ptr);
assert(buffer1 != buffer2);

wrapped1 = wrapped2;

//Everything points to the same stuff as before.
assert(wrapped1.ptr is &buffer1);
assert(wrapped2.ptr is &buffer2);
assert(wrapped1.ptr !is wrapped2.ptr);

//But buffer1 has changed due to the assignment.
assert(buffer1 == [6, 7, 8, 9, 10]);
assert(buffer2 == [6, 7, 8, 9, 10]);

buffer2 = [11, 12, 13, 14, 15];

//Everything points to the same stuff as before.
assert(wrapped1.ptr is &buffer1);
assert(wrapped2.ptr is &buffer2);
assert(wrapped1.ptr !is wrapped2.ptr);

//But buffer2 has changed due to the assignment.
assert(buffer1 == [6, 7, 8, 9, 10]);
assert(buffer2 == [11, 12, 13, 14, 15]);

wrapped2 = null;

//The pointer changed for wrapped2 but not wrapped1.
assert(wrapped1.ptr is &buffer1);
assert(wrapped2.ptr is null);
assert(wrapped1.ptr !is wrapped2.ptr);

//buffer2 is not affected by the assignment.
assert(buffer1 == [6, 7, 8, 9, 10]);
assert(buffer2 == [11, 12, 13, 14, 15]);

Meta