@nogc with opApply

tide tide at tide.tide
Sun Aug 12 01:09:39 UTC 2018


On Saturday, 11 August 2018 at 10:00:34 UTC, Alex wrote:
> Hi all,
> maybe I misunderstand something but having this:
>
> ´´´
> import std.experimental.all;
>
> static assert(isIterable!S);
>
> void main()
> {
>     S s;
>     s.each!(el => el.writeln);
> }
>
> struct S
> {
>     private Nullable!uint member = 0;
>     Nullable!uint front() @nogc { return member; }
>     //void popFront(){} // not implementable.
>     //bool empty(){} // not implementable
>     Nullable!uint successor(uint current) @nogc { return 
> Nullable!uint.init; }
>
>     /**
>     the opApply method grants the correct foreach behavior
>     */
>     int opApply(scope int delegate(ref uint) /*@nogc*/ 
> operations) //@nogc
>     {
>         int result;
>
>         for(auto leading = front; !leading.isNull; leading = 
> successor(leading.get))
>         {
>             result = operations(leading.get);
>
>             if(result)
>             {
>                 break;
>             }
>         }
>         return result;
>     }
> }
> ´´´
>
> Everything works fine, before I try to use the opApply function 
> inside a @nogc function.
>
> If I do, compiler complains, that opApply is not marked as 
> @nogc. Ok.
> If I try to mark opApply @nogc, I would have to mark operations 
> delegate also as @nogc, but I can't do this, as I do not know a 
> priori, how it will be used.
>
> Now, as I learned at some point, a possibility would be, to 
> templatify the function, as the compiler can then derive, if 
> @nogc apply or not.
> But if I write
> ´´´
> int opApply()(...){...}
> ´´´
> Then the static assert from above refuses to compile.
>
> So... how to solve this case?

There's no way to solve it, just don't use @nogc is the easiest 
workaround. It wasn't thought out when it was added and these are 
one of the cases where it doesn't work. Having functions 
automatically declare themselves @nogc if they don't use the gc 
would solve part of the problem. Which is how templates work.

https://dlang.org/library/std/traits/is_iterable.html

If you see how isIterable is defined you'll see that it requires 
opApply be able to provide the element type automatically. That 
is "foreach" doesn't define a type and it is automatically 
deduced. The compiler can't deduce the argument type because the 
function is a template.


     foreach(t ; S.init) // Error: cannot infer type for `foreach` 
variable `t`, perhaps set it explicitly
     {

     }


More information about the Digitalmars-d-learn mailing list