Emplace vs closures

ag0aep6g via Digitalmars-d digitalmars-d at puremagic.com
Mon Sep 19 04:45:25 PDT 2016


On 09/19/2016 01:27 PM, Lodovico Giaretta wrote:
> As we all should know, std.conv.emplace does not play well with closures:
>
> void main()
> {
>     int x = 42;
>     struct S
>     {
>         auto getX() { return x; }
>     }
>
>     S s;
>     assert(s.getX == x);
>
>     auto ps = someBuffer.emplace!S();
>     assert(s.getX == x);                // SEGFAULT!
> }

Should probably be `assert(ps.getX == x);`.

Note that it would also segfault with `auto ps = S.init;`, and for the 
same reason: missing context pointer.

> As this is not fixable (we cannot pass closures around in D), we should
> IMHO forbid such usages of emplace (i.e. static assert(!isNested!S))
>
> I was already working on this, when I stumbled upon this unittest in
> std.conv (simplified):
>
> unittest
> {
>     int i = 0;
>     struct S1
>     {
>         void foo(){++i;}
>     }
>     S1 sa = void;
>     S1 sb;
>     emplace(&sa, sb);   // automagically works
>     sa.foo();
>     assert(i == 1);
> }
>
> Of course there's no way to distinguish between this (legitimate?) use
> case and the former one, so preventing those segfaults will also
> prohibit this kind of usage.

There is a difference, though: You're copying an existing object here, 
including the context pointer. So maybe we could disallow the variant 
above that writes the .init value, and still allow the copying variant.


More information about the Digitalmars-d mailing list