On 5/6/15 3:31 AM, Timon Gehr wrote:
On 05/06/2015 10:01 AM, Andrei Alexandrescu wrote:
Consider:

void fun()
{
     int x;
     class C
     {
         ...
     }
}

Objects of type C have access to x because they have an .outer
pseudo-member.

Problem is, emplace() and any other in-situ initialization techniques
fail (e.g. emplace() will fail with inner classes).

This seems to be a compiler issue - there's no way to initialize outer
without calling new.


The following workaround seems to do it (I didn't test it thoroughly
though, in particular, I didn't test whether escape analysis always
works correctly for this implementation):

T nestedEmplace(T,alias x,S...)(void[] mem,S args){
     auto res=cast(T)mem.ptr;
     enum siz=__traits(classInstanceSize, T);
     (cast(byte[])mem)[0..siz]=typeid(T).init[];
     auto dg=(){ return x; };
     res.outer=dg.ptr;
     static if(is(typeof(res.__ctor(args)))) res.__ctor(args);
     else assert(!is(typeof(&res.__ctor))&&args.length==0);
     return res;
}

void main(){
     int x=12345;
     class C{
         this(){}
         int foo(){
             return x;
         }
     }
     void[__traits(classInstanceSize,C)] mem=void;
     auto c=nestedEmplace!(C,x)(mem);
     assert(c.foo()==12345);
     x=3;
     assert(c.foo()==3);
}

Thanks, that's quite the tour de force. I tried to massage things in various places to avoid changing emplace()'s signature, no avail. I think we have a problem here. -- Andrei

Reply via email to