www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Automatic range creation for class or struct?

reply Peka <nowhere mail.ru> writes:
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.)
Feb 09 2016
next sibling parent reply cym13 <cpicard openmailbox.org> writes:
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); }
Feb 09 2016
next sibling parent reply Peka <nowhere mail.ru> writes:
On Wednesday, 10 February 2016 at 00:22:46 UTC, 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
I need definitive answer.
 but it's not hard to pull it out using mixin templates:
Sure! Thanks a lot, but I want to use std lib as much as possible
Feb 09 2016
parent reply Peka <nowhere mail.ru> writes:
 I don't think anything like that exists in phobos
I need definitive answer.
I need a precise answer. (sorry, google translator :з)
Feb 09 2016
parent cym13 <cpicard openmailbox.org> writes:
On Wednesday, 10 February 2016 at 00:27:54 UTC, Peka wrote:
 I don't think anything like that exists in phobos
I need definitive answer.
I need a precise answer. (sorry, google translator :з)
"Definitive" is good, maybe even better in the context. I should have been clearer, sorry. When I said "I don't think" I actually meant "I've searched the docs and sources and haven't found anything even remotely similar". I'll never be 100% percent sure that it isn't there though, you're free to read phobos to confirm it.
Feb 09 2016
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Feb 09 2016
prev sibling parent Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
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.)
See: https://issues.dlang.org/show_bug.cgi?id=5351
Feb 10 2016