View mode: basic / threaded / horizontal-split · Log in · Help
June 05, 2012
foreach over pointer to range
"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
June 05, 2012
Re: foreach over pointer to range
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.
June 05, 2012
Re: foreach over pointer to range
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.
June 05, 2012
Re: foreach over pointer to range
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
June 05, 2012
Re: foreach over pointer to range
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);
}
June 05, 2012
Re: foreach over pointer to range
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
June 05, 2012
Re: foreach over pointer to range
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 :)
June 05, 2012
Re: foreach over pointer to range
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
Top | Discussion index | About this forum | D home