View source code
Display the source code in std/range/package.d from which this page was generated on github.
Report a bug
If you spot a problem with this page, click here to create a Bugzilla 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 local clone.

std.range.RefRange/refRange - multiple declarations

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

auto auto refRange(R) (
  R* range
)
if (isInputRange!R);

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.

Parameters

NameDescription
range the range to construct the RefRange from

Returns

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.

Example

Basic Example

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

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

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

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

Example

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.
writeln(buffer1); // [6, 7, 8, 9, 10]
writeln(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.
writeln(buffer1); // [6, 7, 8, 9, 10]
writeln(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.
writeln(buffer1); // [6, 7, 8, 9, 10]
writeln(buffer2); // [11, 12, 13, 14, 15]

Example

import std.algorithm.iteration : map, joiner, group;
import std.algorithm.searching : until;
// fix for std.algorithm
auto r = map!(x => 0)([1]);
chain(r, r);
zip(r, r);
roundRobin(r, r);

struct NRAR {
    typeof(r) input;
    @property empty() { return input.empty; }
    @property front() { return input.front; }
    void popFront()   { input.popFront(); }
    @property save()  { return NRAR(input.save); }
}
auto n1 = NRAR(r);
cycle(n1);  // non random access range version

assumeSorted(r);

// fix for std.range
joiner([r], [9]);

struct NRAR2 {
    NRAR input;
    @property empty() { return true; }
    @property front() { return input; }
    void popFront() { }
    @property save()  { return NRAR2(input.save); }
}
auto n2 = NRAR2(n1);
joiner(n2);

group(r);

until(r, 7);
static void foo(R)(R r) { until!(x => x > 7)(r); }
foo(r);

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

struct RefRange(R)
  
if (isInputRange!R);

Constructors

NameDescription
this

Properties

NameTypeDescription
back[get, set] autoOnly defined if isBidirectionalRange!R is true.
empty[get] bool
front[get, set] auto
length[get] autoOnly defined if hasLength!R is true.
ptr[get] inout(R*)A pointer to the wrapped range.
save[get] autoOnly defined if isForwardRange!R is true.

Methods

NameDescription
moveAt Only defined if hasMobileElements!R and isRandomAccessRange!R are true.
moveBack Only defined if hasMobileElements!R and isBidirectionalRange!R are true.
moveFront Only defined if hasMobileElements!R and isForwardRange!R are true.
opAssign 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
opIndex Only defined if isRandomAccesRange!R is true.
opSlice Only defined if isForwardRange!R is true.
opSlice Only defined if hasSlicing!R is true.
popBack Only defined if isBidirectionalRange!R is true.
popFront

Aliases

NameDescription
opDollar Only defined if hasLength!R is true.

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.

Parameters

NameDescription
range the range to construct the RefRange from

Returns

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.

Example

Basic Example

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

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

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

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

Example

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.
writeln(buffer1); // [6, 7, 8, 9, 10]
writeln(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.
writeln(buffer1); // [6, 7, 8, 9, 10]
writeln(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.
writeln(buffer1); // [6, 7, 8, 9, 10]
writeln(buffer2); // [11, 12, 13, 14, 15]

Example

import std.algorithm.iteration : map, joiner, group;
import std.algorithm.searching : until;
// fix for std.algorithm
auto r = map!(x => 0)([1]);
chain(r, r);
zip(r, r);
roundRobin(r, r);

struct NRAR {
    typeof(r) input;
    @property empty() { return input.empty; }
    @property front() { return input.front; }
    void popFront()   { input.popFront(); }
    @property save()  { return NRAR(input.save); }
}
auto n1 = NRAR(r);
cycle(n1);  // non random access range version

assumeSorted(r);

// fix for std.range
joiner([r], [9]);

struct NRAR2 {
    NRAR input;
    @property empty() { return true; }
    @property front() { return input; }
    void popFront() { }
    @property save()  { return NRAR2(input.save); }
}
auto n2 = NRAR2(n1);
joiner(n2);

group(r);

until(r, 7);
static void foo(R)(R r) { until!(x => x > 7)(r); }
foo(r);

Authors

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

License

Boost License 1.0.