can't initialize .outer in inner class
Timon Gehr via Digitalmars-d
digitalmars-d at puremagic.com
Wed May 6 03:31:31 PDT 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
More information about the Digitalmars-d
mailing list