@@ -4273,6 +4273,11 @@ Given a raw memory area $(D chunk), constructs an object of $(D class)
42734273type $(D T) at that address. The constructor is passed the arguments
42744274$(D Args).
42754275
4276+ If `T` is an inner class whose `outer` field can be used to access an instance
4277+ of the enclosing class, then `Args` must not be empty, and the first member of it
4278+ must be a valid initializer for that `outer` field. Correct initialization of
4279+ this field is essential to access members of the outer class inside `T` methods.
4280+
42764281Preconditions:
42774282$(D chunk) must be at least as large as $(D T) needs
42784283and should have an alignment multiple of $(D T)'s alignment. (The size
@@ -4298,18 +4303,30 @@ if (is(T == class))
42984303 // Initialize the object in its pre-ctor state
42994304 chunk[0 .. classSize] = typeid (T).initializer[];
43004305
4306+ static if (isInnerClass! T)
4307+ {
4308+ static assert (Args.length > 0 ,
4309+ " Initializing an inner class requires a pointer to the outer class" );
4310+ static assert (is (Args[0 ] : typeof (T.outer)),
4311+ " The first argument must be a pointer to the outer class" );
4312+
4313+ result.outer = args[0 ];
4314+ alias args1 = args[1 .. $];
4315+ }
4316+ else alias args1 = args;
4317+
43014318 // Call the ctor if any
4302- static if (is (typeof (result.__ctor(args ))))
4319+ static if (is (typeof (result.__ctor(args1 ))))
43034320 {
43044321 // T defines a genuine constructor accepting args
43054322 // Go the classic route: write .init first, then call ctor
4306- result.__ctor(args );
4323+ result.__ctor(args1 );
43074324 }
43084325 else
43094326 {
4310- static assert (args .length == 0 && ! is (typeof (&T.__ctor)),
4327+ static assert (args1 .length == 0 && ! is (typeof (&T.__ctor)),
43114328 " Don't know how to initialize an object of type "
4312- ~ T.stringof ~ " with arguments " ~ Args .stringof);
4329+ ~ T.stringof ~ " with arguments " ~ typeof (args1) .stringof);
43134330 }
43144331 return result;
43154332}
@@ -4327,6 +4344,22 @@ if (is(T == class))
43274344 assert (c.i == 5 );
43284345}
43294346
4347+ @system unittest
4348+ {
4349+ class Outer
4350+ {
4351+ int i = 3 ;
4352+ class Inner
4353+ {
4354+ auto getI () { return i; }
4355+ }
4356+ }
4357+ auto outerBuf = new void [__traits(classInstanceSize, Outer)];
4358+ auto innerBuf = new void [__traits(classInstanceSize, Outer.Inner)];
4359+ auto inner = innerBuf.emplace! (Outer.Inner)(outerBuf.emplace! Outer);
4360+ assert (inner.getI == 3 );
4361+ }
4362+
43304363@nogc pure nothrow unittest
43314364{
43324365 int var = 6 ;
0 commit comments