digitalmars.D - can't initialize .outer in inner class
- Andrei Alexandrescu (17/17) May 06 2015 Consider:
- Timon Gehr (31/49) May 06 2015 The following workaround seems to do it (I didn't test it thoroughly
- Andrei Alexandrescu (4/51) May 06 2015 Thanks, that's quite the tour de force. I tried to massage things in
- Kenji Hara via Digitalmars-d (5/7) May 06 2015 context pointer is runtime data. Then add a way to access the context
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. What would be a proper fix to this? Thanks, Andrei
May 06 2015
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); }What would be a proper fix to this?Probably nested types should invoke nested template instantiation, as the context pointer is runtime data. Then add a way to access the context pointer associated with some symbol (e.g. __traits).Thanks, Andrei
May 06 2015
On 5/6/15 3:31 AM, Timon Gehr wrote:On 05/06/2015 10:01 AM, Andrei Alexandrescu wrote: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. -- AndreiConsider: 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); }
May 06 2015
2015/05/06 19:35 "Timon Gehr via Digitalmars-d" <digitalmars-d puremagic.com: Probably nested types should invoke nested template instantiation, as thecontext pointer is runtime data. Then add a way to access the context pointer associated with some symbol (e.g. __traits). Related: https://issues.dlang.org/show_bug.cgi?id=8863 Kenji Hara
May 06 2015