| |
| Posted by ag0aep6g in reply to vit | PermalinkReply |
|
ag0aep6g
| On 13.06.21 19:49, vit wrote:
> Is possible create and use scope output range allocated on stack in @safe code?
>
> Example:
> ```d
> //-dip1000
>
> struct OutputRange{
> private bool valid = true;
> private void* ptr;
> int count = 0;
>
> void put(Val)(auto ref scope Val val){
> assert(this.valid == true);
> this.count += 1;
> }
>
>
> ~this()scope pure nothrow @safe @nogc{
> this.valid = false;
> }
>
>
> }
>
> void main()@safe pure nothrow @nogc{
> import std.algorithm : copy;
> import std.range : only;
>
> scope OutputRange or;
>
> only(1, 2, 3, 4).copy(&or); ///Error: cannot take address of `scope` local `or` in `@safe` function `main`
> assert(or.count == 4);
> }
>
> ```
You're trying to create a `scope` pointer that points to another `scope` pointer. That's not supported. You can only have one level of `scope`.
The first level of `scope` is explicit in `scope OutputRange or;`. The second level is implicit in `&or`, because the address of a local variable is necessarily a `scope` pointer.
As it's written, the first level isn't actually needed in your code. So maybe you can just remove `scope` from `or` be done. But let's assume that it really is needed for some reason.
The second level you do need. Without it, the assert fails. But you wouldn't need the pointer if `copy` took the argument by `ref`, because `ref` has a sort of implied `scope` that can be combined with an actual `scope` to give two levels of protection. So you could write your own `copy` with a `ref` parameter.
Or you can just write out what `copy` does in `main`, sidestepping the issue:
----
foreach (e; only(1, 2, 3, 4))
{
or.put(e);
}
----
None of this is ideal, of course.
|