Thread overview |
---|
August 11, 2018 @nogc with opApply | ||||
---|---|---|---|---|
| ||||
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? |
August 12, 2018 Re: @nogc with opApply | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | 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 { } |
August 12, 2018 Re: @nogc with opApply | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On 08/11/2018 12:00 PM, Alex wrote: > ´´´ > import std.experimental.all; > > static assert(isIterable!S); > [...] > > struct S > { [...] > int opApply(scope int delegate(ref uint) /*@nogc*/ operations) //@nogc > { [...] > } > } > ´´´ > > 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? You can provide to overloads: one with @nogc, one without it. To keep it somewhat DRY, you can let them forward to a template implementation: int opApply(scope int delegate(ref uint) operations) { return opApplyImpl(operations); } int opApply(scope int delegate(ref uint) @nogc operations) @nogc { return opApplyImpl(operations); } int opApplyImpl(O)(O operations) { /* ... implementation here ... */ } |
August 12, 2018 Re: @nogc with opApply | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Sunday, 12 August 2018 at 01:39:21 UTC, ag0aep6g wrote:
> On 08/11/2018 12:00 PM, Alex wrote:
>> [...]
> [...]
>> [...]
> [...]
>> [...]
> [...]
>> [...]
>
> You can provide to overloads: one with @nogc, one without it. To keep it somewhat DRY, you can let them forward to a template implementation:
>
> int opApply(scope int delegate(ref uint) operations)
> {
> return opApplyImpl(operations);
> }
> int opApply(scope int delegate(ref uint) @nogc operations) @nogc
> {
> return opApplyImpl(operations);
> }
> int opApplyImpl(O)(O operations)
> {
> /* ... implementation here ... */
> }
Ah... that's nice...
Thanks!
|
Copyright © 1999-2021 by the D Language Foundation