September 28

😁

Try the 2nd usage, D is a very flexible language; moves towards perfection!

struct Sarma {
    int i;
    // mixin DownRange;
}

struct Foo(T) {
    int[] array;
                       // 1. USAGE
    auto opApply(scope int delegate(T) dg) {
        foreach (ref e; array)
        {
            auto result = dg(T(e));
        }
        return 0;
    }

    auto opApply(scope // 2. USAGE
    int delegate(size_t, int, ref int) dg) {
        int count;
        foreach (i, ref e; array)
        {
            e *= 15;
            ++count;
            auto result = dg(i, count, e);
        }
        return 0;
    }
}
import std.stdio;
void main()
{
    auto foo = Foo!Sarma( [2, 4, 6] );

    foreach (Sarma e; foo)
    {
        e.write(" ");
    }
    writeln;

    foreach (i, s, ref e; foo)
    {
        s.writef!"counter = %s, ";
        i.writeln(": ", e++);
    }
    foo.array.writeln;
}

template DownRange() {
    bool empty() { return i <= 0; }
    auto front() { return i; }
    void popFront() { --i; }
}

It may be explained in specific documentation (on 12.11.11).

https://dlang.org/spec/statement.html#foreach_over_arrays

SDB@79