Variables with scoped destruction in closures

Nordlöw via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Oct 14 03:18:19 PDT 2016


The following code


import std.algorithm.iteration : filter;
import std.algorithm.mutation : move;
import std.range : iota;

static private struct S
{
     import core.memory : GC;
     @disable this(this);

     this(int x)
     {
         _ptr = cast(typeof(_ptr))GC.malloc((*_ptr).sizeof);
         *_ptr = x;
     }

     ~this() { GC.free(_ptr); }  // scoped destruction

     @property auto ref value() @safe pure nothrow @nogc { return 
*_ptr; }
     alias value this;

     int* _ptr;
}

auto below1(size_t n,
             S s = S.init)
{
     // this could work, if the compiler could infer that
     // `s` can be implicitly converted to an r-value
     return 0.iota(n).filter!(_ => _ < s);
}

auto below2(size_t n,
             S s = S.init)
{
     // this should work, because `s` is an r-value
     return 0.iota(n).filter!(_ => _ < s.move());
}

unittest
{
     S s = S(42);
     s.value = 43;
     s.value = 42;
     assert(s.value == 42);

     // both these fail
     100.below1(s.move());
     100.below2(s.move());
}



fails to compile with DMD Git master with error message

t_scope.d(23,6): Error: variable t_scope.below.s has scoped 
destruction, cannot build closure

It illustrates one the simplest cases where a container-type 
cannot be used inside a lambda closure needed by D's great lazy 
ranges.

Can somebody explain why not even `below2` compiles eventhough 
`s.move()` is inferred to be an r-value?

Until this gets fixed in the compiler, is there something I can 
do in the mean-while to make it possible to use instances of `S` 
inside of range lambda closures?


More information about the Digitalmars-d-learn mailing list