Disabled and enabled copy constructors and .dup
Biotronic
simen.kjaras at gmail.com
Tue Oct 24 12:06:54 UTC 2017
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
More information about the Digitalmars-d-learn
mailing list