我即将编写一个解析器来逐行读取文本文件到不同类型的结构中,并将这些结构赋予回调(观察者或访问者 - 尚不确定).
该文本文件包含MT-940数据 - SWIFT银行对帐单.
这些行包含一个指定类型的标记和一些字段 - 例如日期 - 应该被解析为我的消息的类型安全成员.其中一些字段是可选的 - 所以我的问题是:我如何在D中表示可选值.
C++提供了你可能知道的boost :: optional之类的东西.
我目前正在通过自己实现一个Optional(T)来解决这个问题(参见本文末尾的代码).它是一个包含ValueHolder实例的结构,该实例可能为null - 这标记了没有赋值的情况.我覆盖了copy-c'tor和赋值运算符,以便在必要时创建ValueHolder的深层副本.
这是要走的路吗?还有其他 - 更简单 - 我看不到的选项吗?
这是我的代码 - 不一定完成功能:
struct Optional(T)
{
class ValueHolder
{
T value;
this(T v)
{
value = v;
}
}
private ValueHolder m_value;
/* Construction without value / with value */
this(T value)
{
m_value = new ValueHolder(value);
}
/* Copy construction / assignment */
ref Optional!(T) opAssign(Optional!(T) rhs)
out
{
if (rhs.m_value !is null)
{
assert(rhs.m_value != m_value);
}
else
{
assert(m_value is null);
}
}
body
{
m_value = null;
if (rhs)
{
m_value = new ValueHolder(rhs.m_value.value);
}
return this;
}
ref Optional!(T) opAssign(T value)
out
{
assert(hasValue());
assert(m_value.value == value);
}
body
{
if (m_value is null)
{
m_value = new ValueHolder(value);
}
else
{
m_value.value = value;
}
return this;
}
this(Optional!(T) rhs)
out
{
if (rhs.m_value !is null)
{
assert(rhs.m_value != m_value);
}
else
{
assert(m_value is null);
}
}
body
{
if (rhs.m_value !is null)
{
m_value = new ValueHolder(rhs.m_value.value);
}
}
/* Implicit cast to bool */
bool hasValue() const
{
return m_value !is null;
}
X opCast(X: bool)()
{
return hasValue();
}
/* Value access */
T opUnary(string s)() const
in
{
assert(s == "*");
assert(m_value !is null);
}
body
{
return m_value.value;
}
}
/* Default Constructed Struct does not have a value assigned */
unittest
{
Optional!(int) x;
assert(x.hasValue() == false);
assert(!x);
}
/* Construction with value */
unittest
{
Optional!(int) x = 3;
assert(x);
assert(x.hasValue());
}
/* Assignment operator does copy the value */
unittest
{
Optional!(int) x = 3;
Optional!(int) y;
assert(x);
assert(!y);
y = x;
assert(&x != &y);
assert(x);
assert(y);
y = 12;
assert(x.m_value.value != y.m_value.value);
assert(*y == 12);
Optional!(int) z;
x = z;
assert(!x);
assert(!z);
assert(y);
}
Run Code Online (Sandbox Code Playgroud)