On Friday, 18 September 2020 at 14:14:31 UTC, Andrey Zherikov
wrote:
It seems that dtor is called at exit from lazy delegate, not at
exit form create():
======
create()
.do_something()
.do_lazy()
.do_something();
======
Output:
======
-> void test.main()
-> test.do_lazy(lazy S s)
-> test.create()
1 S test.S.this(int n)
<- test.create()
-> 1 test.do_something(S s)
<- 1 test.do_something(S s)
1 void test.S.~this()
===-1
<- test.do_lazy(lazy S s)
-> 1703096 test.do_something(S s)
<- 1703096 test.do_something(S s)
<- void test.main()
======
This doesn't even allow me to copy the value of 's' in
do_lazy().
You're right, I missed a step: do_lazy() takes a S, not a
scoped!S, so the conversion from scoped!S to S happens after
create() has returned and before the value is used in do_lazy.
This explains my confusion earlier.
D's lazy is essentially the same as a delegate or function, so
you could* rewrite to this (writelns omitted for clarity):
S do_lazy(S function() s) {
return s();
}
void main() {
(() => cast(S)create()) // Here
.do_lazy()
.do_something();
}
On the marked line, the cast from scoped!S to S happens, the
scoped!S goes out of scope and the destructor is called.
*There may be differences, but for this discussion these are not
important.
--
Simen