each & opApply

Steven Schveighoffer schveiguy at yahoo.com
Wed May 23 13:49:45 UTC 2018


On 5/23/18 9:37 AM, Alex wrote:
> This is a question is about usage of
> ´each´
> https://dlang.org/phobos/std_algorithm_iteration.html#each
> 
> with a type where different opApply overloads are defined. Say, I have 
> something like this:
> 
> ´´´
> void main()
> {
>      import std.stdio : writeln;
>      import std.algorithm : each;
> 
>      auto c = Container();
> 
>      c.arr1.length = 50;
>      c.arr2.length = 5;
> 
>      c.each!((a, b) => writeln(a, b));
>          //c.each!(a => writeln(a)); // why this line does not compile?
> }
> 
> struct El1{}
> struct El2{}
> 
> struct Container
> {
>      El1[] arr1;
>      El2[] arr2;
> 
>      //http://ddili.org/ders/d.en/foreach_opapply.html
>      int opApply(int delegate(ref El1, ref El2) operations){ assert(0); }
>      int opApply(int delegate(ref El2) operations){ assert(0); }
>      int opApply(int delegate(ref El1) operations){ assert(0); }
>      int opApply(int delegate(ref El2, ref El1) operations){ assert(0); }
> }
> ´´´
> 
> The compilation error on the last line in the main is:
> 
> /usr/local/opt/dmd/include/dlang/dmd/std/algorithm/iteration.d(966,21): 
> Error: template `D main.__lambda2` cannot deduce function from argument 
> types `!()(El1, El2)`, candidates are:
> source/app.d(12,13):        `app.main.__lambda2`
> source/app.d(12,6): Error: template instance `app.main.each!((a) => 
> writeln(a)).each!(Container)` error instantiating
> 
> So... I get the idea, that ´each´ looks only on the first opApply 
> overload, right?

Apparently, but that's not very good. IMO, it should use the same rules 
as foreach. In which case, BOTH lines should fail to compile.

> Is there any possibility, to convince it to use a specific one? Say, for 
> the last line in the main, to use the third overload of opApply?
> 
> By the way, iterating via foreach works as expected: each of
> 
> ´´´
> foreach(El1 el; c){}
> foreach(El2 el; c){}
> foreach(El1 el1, El2 el2; c){}
> foreach(El2 el1, El1 el2; c){}
> ´´´
> 
> compiles and iterates as it should.

Right, but not foreach(el1, el2; c), which is the equivalent of your 
each call.

-Steve


More information about the Digitalmars-d-learn mailing list