How to implement this?
    Ali Çehreli 
    acehreli at yahoo.com
       
    Fri Apr  8 05:18:38 UTC 2022
    
    
  
On 4/7/22 21:31, Elvis Zhou wrote:
 >
 > struct A {}
 > struct B { A a; }
 > struct C { A a; }
 >
 > A*[] structs;
 >
 > B b;
 > init(&b);
 > structs ~= cast(A*)&b;
 > //Error: copying `cast(A*)& b` into allocated memory escapes a reference
 > to local variable `b`
If that really is the case, you want to place the objects on memory that 
will not go away. Dynamic arrays provide "memory" that is owned by the GC.
The following program emplaces alternating Bs and Cs into a buffer and 
then batch_process'es them:
struct A { int i; }
struct B { A a; }
struct C { A a; }
A*[] structs;
void append(T, Args...)(ref ubyte[] structs, Args args) {
   import std.conv : emplace;
   structs.length += sizeWithPadding!T;
   auto where = cast(T*)(&structs[$ - sizeWithPadding!T]);
   emplace(where, args);
}
void main() {
   ubyte[] structs;
   foreach (i; 0 .. 10) {
     if (i % 2) {
       structs.append!B(A(i));
     } else {
       structs.append!C(A(i));
     }
   }
   batch_process(structs);
}
auto process(T)(const(ubyte)[] structs) {
   import std.stdio : writeln;
   writeln(*cast(T*)structs.ptr);
   return structs[sizeWithPadding!T..$];
}
void batch_process(const(ubyte)[] structs) {
   import std.range : empty;
   for (size_t i = 0; !structs.empty; i++) {
     if (i % 2) {
       structs = structs.process!B();
     } else {
       structs = structs.process!C();
     }
   }
}
T * nextAlignedAddress(T)(T * candidateAddr) {
   import std.traits;
   static if (is (T == class)) {
     const alignment = classInstanceAlignment!T;
   } else {
     const alignment = T.alignof;
   }
   const result = (cast(size_t)candidateAddr + alignment - 1)
                  / alignment * alignment;
   return cast(T*)result;
}
void * nextAlignedAddress(T)(void * candidateAddr) {
   return nextAlignedAddress(cast(T*)candidateAddr);
}
size_t sizeWithPadding(T)() {
   static if (is (T == class)) {
     const candidateAddr = __traits(classInstanceSize, T);
   } else {
     const candidateAddr = T.sizeof;
   }
   return cast(size_t)nextAlignedAddress(cast(T*)candidateAddr);
}
I copied nextAlignedAddress() and sizeWithPadding() functions from this 
chapter:
   http://ddili.org/ders/d.en/memory.html
Everything I did in the program above is explained there.
Ali
    
    
More information about the Digitalmars-d-learn
mailing list