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
    {

    }

Reply via email to