On Sunday, 24 September 2017 at 18:46:15 UTC, Haridas wrote:
Also consider the following code. Please let me know if I am
doing the right thing for dynamic arrays. My hack seems to have
the desired effect on shutting down the destructor. Is this
hack legal use of D? Can you please guide me if/how it can be
achieved for std.container.Array?
// >>>>
import std.stdio;
struct Bar {
~this() {
writeln("~Bar");
}
}
void main() {
{ // dynamic array
Bar[] bars;
bars.length = 4;
void* tmp = bars.ptr;
delete(tmp);
bars.length = 0;
}
{ // std.container.Array
import std.container: Array;
Array!Bar bars;
bars.length = 6;
// does not seem to work
void* tmp = &(bars[0]);
delete(tmp);
bars.length = 0;
}
}
Since you're deleting the memory the dynamic array is pointing
to, what you're doing is potentially unsafe - if anyone touches
that memory after it's been deleted, nasal demons may follow.
What you want is something like this:
import std.stdio;
struct Bar
{
this(int n) {}
~this()
{
writeln("~Bar");
}
}
struct SuppressGC(T)
{
// Disguise T as a humble array.
private ubyte[T.sizeof] _payload;
// Create from instance of T.
this(T arg) {
_payload = *cast(ubyte[T.sizeof]*)&arg;
}
// Or forward constructor arguments to T's constructor.
static if (__traits(hasMember, T, "__ctor"))
{
this(Args...)(Args args)
if (__traits(compiles, (Args e){__traits(getMember,
T.init, "__ctor")(e);}))
{
__traits(getMember, get, "__ctor")(args);
}
}
// Pretend to be a T.
@property
ref T get()
{
return *cast(T*)_payload.ptr;
}
alias get this;
}
void useBar(ref Bar b) {}
unittest
{
// Construct from instance.
//This creates a temporary on the stack, and its destructor
will be called.
SuppressGC!Bar a = Bar(3);
// Or by forwarding constructor arguments.
// This constructs in-place inside SuppressGC, and no
destructor will be called.
auto b = SuppressGC!Bar(3);
SuppressGC!Bar[] arr;
arr.length = 3;
// Another stack temporary. Destructor will be called.
arr[0] = Bar(5);
// No temp
arr[1] = SuppressGC!Bar(5);
// It even pretends to be the wrapped struct:
useBar(b);
}
In general, of course, this is a bad idea - there's probably a
reason that destructor does the thing it's doing. If you're sure
skipping it is what you want, go ahead.
--
Biotronic