0
点赞
收藏
分享

微信扫一扫

d重绑定不变


​​原文​​

// Nullable,如何更好工作?技术上是`安全`的,但真不是.
module turducken;

import std.algorithm;
import std.datetime;

// 如何在`邪恶类型`上,早期解除绑定,并再后期绑定
// Turducken是答案.

// 先,设置舞台,值构类型
struct S
{
// 有一个引用不变数据的不变值字段
immutable int[] i;

// SysTime:过去和我冲突
SysTime st;

// 无默认
@disable this();

// 违反其不变量的.init
bool properlyInitialized = false;

invariant { assert(properlyInitialized); }

// 重载复制赋值,可禁止复制赋值.
void opAssign(S) { assert(false); }

// 为确认每个构造函数调用都匹配析构函数调用,它计算引用
int *refs;

this(int* refs)
pure @safe @nogc
{
this.properlyInitialized = true;
this.refs = refs;
(*refs)++;
}

this(this)
pure @safe @nogc
{ (*refs)++; }

// 既然定义了析构函数,我们肯定会,断定已破坏`.init`.
~this()
pure @safe @nogc
in(refs)
out(; *refs >= 0)
do { (*refs)--; }
}

// 挑战!
//函数为:
pure // pure,
@safe // safe,
@nogc // 及nogc:
unittest
{
// 干后期绑定和早期解除绑定

// 准备

// (验证)
int refs;

// (欺骗)
int* refsp = () @trusted { return &refs; }();

{
// 从默认初化变量开始
Turducken!S magic;
// 绑定到已构造值
magic.bind(S(refsp));

// 只一份
assert(refs == 1);

// 为了开心,绑定它
magic.bind(S(refsp));

// 仍然只有一个副本
assert(refs == 1);

// 包含的值一切正常
assert(magic.value.properlyInitialized);

// 域结束前解除绑定
magic.unbind;

// S离开了
assert(refs == 0);
}
// 只析构一次,正确.
assert(refs == 0);
}

// 如何完成
// Turducken!
struct Turducken(T)
{
// 美味中心
alias Chicken = T;

//Union确保不调用T析构函数
union Duck
{
Chicken chicken; //
}

//确保可用moveEmplace及神奇(违反常)的memcpy的构
struct Turkey
{
Duck duck;
}

Turkey store = Turkey.init; // 火鸡店

bool set = false;

// 插入吸管,进入中心
@property ref T value() in(set) { return store.duck.chicken; }

// 特制的酱汁
void bind(T value)
{
// 为防几秒后回来,清理
unbind;

//制作析构器保护的副本来粘贴在我们商店中
Turkey wrapper = Turkey(Duck(value));

// 忽略常,遍历数据.
() @trusted { moveEmplace(wrapper, store); }();

set = true;
}

// 调味品
void unbind()
{
if (set)
{
static if (is(T == struct)) {
destroy(value);
}
set = false;
}
}

// 因为已经避免了值受D的监视,
// 必须手动清理
~this()
{
unbind;
}
}

这就是​​火鸡​​技术!


举报

相关推荐

0 条评论