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