[Issue 5351] Add template mixin for Range Primitives using random access

d-bugmail at puremagic.com d-bugmail at puremagic.com
Mon Oct 30 20:16:55 UTC 2017


https://issues.dlang.org/show_bug.cgi?id=5351

Simen Kjaeraas <simen.kjaras at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras at gmail.com

--- Comment #3 from Simen Kjaeraas <simen.kjaras at gmail.com> ---
The implementation above will fail for this simple case:

MyRange!int a = [1,2,3];
a.popFront();
assert(a[0] == a.front);

It could be made to work for ranges that support slicing, and assignment from
the slice to the range:

void popFront() {
    this = this[1..$];
}

front and empty are then trivial calls to this[0] and length == 0,
respectively.

One option that only requires opIndex and length would use a wrapper struct.
This solution would leave MyRange as a non-range, though - only its sliced
result would be a range:

struct MyRange(T) {
    T[] arr;
    T opIndex(size_t idx) {
        return arr[idx];
    }

    @property
    size_t length() {
        return arr.length;
    }

    mixin rangeFuncs!();
}

template rangeFuncs() {
    auto opSlice() {
        alias TT = typeof(this);
        struct Result {
            size_t _index;
            TT* _range;

            auto front() {
                return (*_range)[_index];
            }

            @property
            bool empty() {
                return _index == _range.length;
            }

            void popFront() {
                _index++;
            }

            auto opIndex(size_t idx) {
                return (*_range)[_index + idx];
            }
        }

        Result result;
        result._range = &this;
        return result;
    }
}

unittest {
    import std.range.primitives : isInputRange;
    import std.algorithm.comparison : equal;

    auto a = MyRange!int([1,2,3,4]);

    static assert(!isInputRange!(typeof(a)));
    static assert(isInputRange!(typeof(a[])));
    assert(a[].equal([1,2,3,4]));
}

In conclusion, opIndex + length is insufficient functionality to turn something
into a range.

--


More information about the Digitalmars-d-bugs mailing list