www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach over pointer to range

reply Artur Skawina <art.08.09 gmail.com> writes:
"foreach (e; pointer_to_range)" currently fails with:

   Error: foreach: Range* is not an aggregate type

It can be worked around with 

   struct RangePtr(R) {
      R* ptr;
      alias ptr this;
       property front()() { return ptr.front; }
   }

but this adds unnecessary overhead (unfortunately such struct is not
always treated the same as a real pointer, eg when passing it around).

Is there some reason that makes the is-aggregate check necessary, or could
it be dropped?


Thanks,

artur
Jun 05 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/05/2012 08:42 PM, Artur Skawina wrote:
 "foreach (e; pointer_to_range)" currently fails with:

     Error: foreach: Range* is not an aggregate type

 It can be worked around with

     struct RangePtr(R) {
        R* ptr;
        alias ptr this;
         property front()() { return ptr.front; }
     }

 but this adds unnecessary overhead (unfortunately such struct is not
 always treated the same as a real pointer, eg when passing it around).

 Is there some reason that makes the is-aggregate check necessary, or could
 it be dropped?


 Thanks,

 artur

It should be dropped. A pointer to range is a perfectly fine range.
Jun 05 2012
next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 06/05/12 21:25, Peter Alexander wrote:
 On Tuesday, 5 June 2012 at 18:46:51 UTC, Timon Gehr wrote:
 On 06/05/2012 08:42 PM, Artur Skawina wrote:
 "foreach (e; pointer_to_range)" currently fails with:

    Error: foreach: Range* is not an aggregate type

 It can be worked around with...


Why not: foreach(e; *pointer_to_range) Seems like the obvious solution to me, and works.

Works by copying the whole range struct, which is what I don't want to happen. And no, using a class is not an option. :) artur
Jun 05 2012
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 06/05/12 22:23, simendsjo wrote:
 On Tue, 05 Jun 2012 20:46:51 +0200, Timon Gehr <timon.gehr gmx.ch> wrote:
 
 It should be dropped. A pointer to range is a perfectly fine range.

Sure..? I couldn't get it to work either: struct R { string test = "aoeu"; property front() { return test[0]; } property bool empty() { return !test.length; } void popFront(){test = test[0..$];} } void main() { R r; R* p = &r; foreach(ch; p) // invalid foreach aggregate p writeln(ch); }

It /is/ a valid range, but it's /not/ currently accepted by foreach. So you have to write the above as: struct R { string test = "aoeu"; property front() { return test[0]; } property bool empty() { return !test.length; } void popFront(){test = test[0..$];} } struct RangePtr(R) { R* ptr; alias ptr this; property front()() { return ptr.front; } } void main() { R r; auto p = RangePtr!R(&r); foreach(ch; p) writeln(ch); } which works, but only obfuscates the code and can be less efficient. artur
Jun 05 2012
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 06/05/12 22:41, simendsjo wrote:
 On Tue, 05 Jun 2012 22:38:22 +0200, Artur Skawina <art.08.09 gmail.com> wrote:
 
 On 06/05/12 22:23, simendsjo wrote:
 On Tue, 05 Jun 2012 20:46:51 +0200, Timon Gehr <timon.gehr gmx.ch> wrote:

 It should be dropped. A pointer to range is a perfectly fine range.

Sure..? I couldn't get it to work either: struct R { string test = "aoeu"; property front() { return test[0]; } property bool empty() { return !test.length; } void popFront(){test = test[0..$];} } void main() { R r; R* p = &r; foreach(ch; p) // invalid foreach aggregate p writeln(ch); }

It /is/ a valid range, but it's /not/ currently accepted by foreach.

 which works, but only obfuscates the code and can be less efficient.

Well, then it's not a *perfectly fine* range, is it then :)

It *is* a perfectly fine range; the problem is with 'foreach'. artur
Jun 05 2012
prev sibling next sibling parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Tuesday, 5 June 2012 at 18:46:51 UTC, Timon Gehr wrote:
 On 06/05/2012 08:42 PM, Artur Skawina wrote:
 "foreach (e; pointer_to_range)" currently fails with:

    Error: foreach: Range* is not an aggregate type

 It can be worked around with...


Why not: foreach(e; *pointer_to_range) Seems like the obvious solution to me, and works.
Jun 05 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On Tue, 05 Jun 2012 20:46:51 +0200, Timon Gehr <timon.gehr gmx.ch> wrote:

 It should be dropped. A pointer to range is a perfectly fine range.

Sure..? I couldn't get it to work either: struct R { string test = "aoeu"; property front() { return test[0]; } property bool empty() { return !test.length; } void popFront(){test = test[0..$];} } void main() { R r; R* p = &r; foreach(ch; p) // invalid foreach aggregate p writeln(ch); }
Jun 05 2012
prev sibling parent simendsjo <simendsjo gmail.com> writes:
On Tue, 05 Jun 2012 22:38:22 +0200, Artur Skawina <art.08.09 gmail.com>  
wrote:

 On 06/05/12 22:23, simendsjo wrote:
 On Tue, 05 Jun 2012 20:46:51 +0200, Timon Gehr <timon.gehr gmx.ch>  
 wrote:

 It should be dropped. A pointer to range is a perfectly fine range.

Sure..? I couldn't get it to work either: struct R { string test = "aoeu"; property front() { return test[0]; } property bool empty() { return !test.length; } void popFront(){test = test[0..$];} } void main() { R r; R* p = &r; foreach(ch; p) // invalid foreach aggregate p writeln(ch); }

It /is/ a valid range, but it's /not/ currently accepted by foreach.

 which works, but only obfuscates the code and can be less efficient.

 artur

Well, then it's not a *perfectly fine* range, is it then :)
Jun 05 2012