Thread overview
foreach over pointer to range
Jun 05, 2012
Artur Skawina
Jun 05, 2012
Timon Gehr
Jun 05, 2012
Peter Alexander
Jun 05, 2012
Artur Skawina
Jun 05, 2012
simendsjo
Jun 05, 2012
Artur Skawina
Jun 05, 2012
simendsjo
Jun 05, 2012
Artur Skawina
June 05, 2012
"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
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
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
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
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
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
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
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