Thread overview | ||||||
---|---|---|---|---|---|---|
|
October 24, 2017 Disabled and enabled copy constructors and .dup | ||||
---|---|---|---|---|
| ||||
If I have a `struct X` (container in my case) with disabled copying (postblit) and instead a .dup property, is it somehow possible, unsafe or not, to have `X` as a member of another `struct Y` with an enabled copy constructor which calls `X.dup`? |
October 24, 2017 Re: Disabled and enabled copy constructors and .dup | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On Tuesday, 24 October 2017 at 07:33:43 UTC, Per Nordlöw wrote: > If I have a `struct X` (container in my case) with disabled copying (postblit) and instead a .dup property, is it somehow possible, unsafe or not, to have `X` as a member of another `struct Y` with an enabled copy constructor which calls `X.dup`? With the same approach outline in https://forum.dlang.org/post/nakguitssvjdclpgwhmk@forum.dlang.org, it is indeed possible. In fact, simply using SuppressGC!X should enable it. Note however, that since the point of SuppressGC is to not call the object's destructor (and thus its name is poorly chosen by yours truly), you will need to do so explicitly. Updating the approach to only suppress postblits: struct SuppressPostblit(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; static if (__traits(hasMember, T, "__dtor")) { ~this() { __traits(getMember, get, "__dtor")(); } } } -- Simen |
October 24, 2017 Re: Disabled and enabled copy constructors and .dup | ||||
---|---|---|---|---|
| ||||
Posted in reply to Biotronic | On Tuesday, 24 October 2017 at 07:56:34 UTC, Biotronic wrote:
> struct SuppressPostblit(T)
> {
> // Disguise T as a humble array.
> private ubyte[T.sizeof] _payload;
> ...
A bit too hackish for my taste, but does the job still.
Thanks.
|
October 24, 2017 Re: Disabled and enabled copy constructors and .dup | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On Tuesday, 24 October 2017 at 11:37:42 UTC, Per Nordlöw wrote:
> On Tuesday, 24 October 2017 at 07:56:34 UTC, Biotronic wrote:
>> struct SuppressPostblit(T)
>> {
>> // Disguise T as a humble array.
>> private ubyte[T.sizeof] _payload;
>> ...
>
> A bit too hackish for my taste, but does the job still.
>
> Thanks.
Cleaned up and slightly less hackish (yeah, it bothered me too):
enum SuppressOptions {
destructor = 1,
postblit = 2
}
struct Suppress(T, SuppressOptions options) if (options != 0)
{
import std.traits : isCopyable;
private enum suppressPostblit = (options & SuppressOptions.postblit) != 0;
private enum suppressDestructor = (options & SuppressOptions.destructor) != 0;
private enum postblitName = __traits(hasMember, T, "__xpostblit") ? "__xpostblit" : "__postblit";
// 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);
}
}
// Call dtor
static if (!suppressDestructor) {
~this() {
destroy(get);
}
}
// Call postblit
static if (!suppressPostblit) {
static if (!isCopyable!T) {
@disable this(this);
} else static if (__traits(hasMember, T, postblitName)) {
this(this) {
__traits(getMember, get, postblitName)();
}
}
}
// Pretend to be a T.
@property
ref T get()
{
return *cast(T*)_payload.ptr;
}
alias get this;
}
struct S1 {
@disable this(this);
~this() {
throw new Exception("Don't touch my destructor!");
}
}
unittest {
import std.exception;
static assert(!__traits(compiles, (Suppress!S1 a) { auto b = a; }));
static assert(__traits(compiles, (Suppress!(S1, SuppressOptions.postblit) a) { auto b = a; }));
assertThrown({ Suppress!(S1, SuppressOptions.postblit) a; }());
assertNotThrown({ Suppress!(S1, SuppressOptions.postblit | SuppressOptions.destructor) a; }());
}
--
Biotronic
|
Copyright © 1999-2021 by the D Language Foundation