On 02/09/2016 04:22 PM, cym13 wrote:
On Wednesday, 10 February 2016 at 00:05:36 UTC, Peka wrote:
Hi!

I have class (or struct) which realises .length() and .opIndex(size_t)
methods.

It is possible to create from this class some sort of range using
template from std? (I mean that internal counter, .popFront(),
.empty() etc methods should be added by template.)

I don't think anything like that exists in phobos but it's not hard to
pull it out using mixin templates:


mixin template Rangify(T)
if (__traits(hasMember, T, "length")
  && __traits(hasMember, T, "opIndex")) {

     ulong _counter;

     bool empty() {
         return _counter == this.length;
     }

     auto front() {
         return this[_counter];
     }

     auto popFront() {
         _counter++;
     }
}

struct S {
     int[] arr;

     mixin Rangify!S;

     auto length() {
         return arr.length;
     }

     int opIndex(size_t i) {
         return arr[i];
     }
}

void main(string[] args) {
     import std.stdio: writeln;

     auto s = S();
     s.arr = [1, 2, 3];

     foreach (x ; s)
         writeln(x);
}


Actually, your method can work non-intrusively if the template is a function that returns a range (typically Voldemort):

auto rangify(T)(T range)
if (__traits(hasMember, T, "length")
 && __traits(hasMember, T, "opIndex")) {

    struct Range {
        T range;
        ulong _counter;

        bool empty() {
            return _counter == range.length;
        }

        auto front() {
            return range[_counter];
        }

        auto popFront() {
            _counter++;
        }
    }

    return Range(range);    // <-- Now returns a Voldemort object
}

struct S {         // <-- No mixin needed
    int[] arr;

    auto length() {
        return arr.length;
    }

    int opIndex(size_t i) {
        return arr[i];
    }
}

void main(string[] args) {
    import std.stdio: writeln;

    auto s = S();
    s.arr = [1, 2, 3];

    foreach (x ; s.rangify)    // <-- CHANGED
        writeln(x);
}

Ali

Reply via email to