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
{
}