在D中表示可选值

时间:2014-08-04 19:59:07

标签: d phobos

我即将编写一个解析器来逐行读取文本文件到不同类型的结构中,并将这些结构提供给回调(观察者或访问者 - 还不确定)。

该文本文件包含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);
}

1 个答案:

答案 0 :(得分:9)

对于可选值,D标准库在模块std.typecons中提供结构模板Nullable

相关问题