Automatic range creation for class or struct?

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Feb 9 17:15:29 PST 2016


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



More information about the Digitalmars-d-learn mailing list