原创作者: oldrev
阅读:974次
评论:0条
更新时间:2011-05-26
boost.variant 是安全、范型、基于栈的可识别联合容器,下面的代码是其在D语言中的等价实现。借助D语言强大的元编程能力,其与C++的版本相比,代码清晰,对类型安全有更大的保证。
- boost.variant 文档:http://www.boost.org/doc/html/variant.html
- boost.any 和 boost.variant 的区别与比较: http://www.boost.org/doc/html/variant/misc.html#variant.versus-any
cpp 代码
- // Module: variant.d
- // Author: Oldrev (wstring#AT#gmail.com)
- // License: BSD
- module variant;
- import std.typetuple;
- import std.traits;
- import std.stdio;
- private template MaxSizeImp(T, V...)
- {
- static if(V.length > 0)
- private const int tailResult = MaxSizeImp!(V).result;
- else
- private const int tailResult = T.sizeof;
- public const int result = T.sizeof > tailResult ? T.sizeof : tailResult;
- };
- private template MaxSize(TList...)
- {
- const int MaxSize = MaxSizeImp!(TList).result;
- }
- struct Variant(TList...)
- {
- public alias TList TypeList;
- public alias Variant!(TypeList) SelfType;
- private alias ubyte[MaxSize!(TypeList)] Holder;
- private Holder m_held;
- private int m_which = -1;
- public int which()
- {
- return m_which;
- }
- public SelfType assign(ValueType)(ValueType val)
- {
- static if(is(ValueType == SelfType))
- {
- m_held[] = val.m_held[];
- m_which = which;
- }
- else
- {
- const int i = IndexOf!(ValueType, TypeList);
- static assert(i >= 0);
- ValueType* heldPtr = cast(ValueType*)m_held.ptr;
- *heldPtr = val;
- m_which = i;
- }
- return *this;
- }
- public SelfType opAssign(ValueType)(ValueType rhs)
- {
- return assign!(ValueType)(rhs);
- }
- public bool opEquals(ValueType)(ValueType rhs)
- {
- assert(!empty);
- static if(is(ValueType == SelfType))
- {
- foreach(T; TypeList)
- {
- const int i = IndexOf!(T, TypeList);
- if(i == which)
- {
- return (rhs.which == which) && (get!(T) == rhs.get!(T));
- }
- }
- }
- else
- {
- const int i = IndexOf!(ValueType, TypeList);
- static assert(i >= 0);
- return get!(ValueType)() == rhs;
- }
- }
- public int opCmp(ValueType)(ValueType rhs)
- {
- if(rhs == *this)return 0;
- static if(is(ValueType == SelfType))
- {
- foreach(T; TypeList)
- {
- const int i = IndexOf!(T, TypeList);
- if((i == which) && (rhs.which == which))
- {
- return get!(T) < rhs.get!(T) ? -1 : 1;
- }
- }
- }
- else
- {
- const int i = IndexOf!(ValueType, TypeList);
- static assert(i >= 0);
- return get!(ValueType)() < rhs ? -1 : 1;
- }
- }
- public TypeInfo type()
- {
- foreach(T; TypeList)
- {
- const int i = IndexOf!(T, TypeList);
- if(i == which)
- {
- return typeid(TypeList[i]);
- }
- }
- }
- public ValueType get(ValueType)()
- {
- assert(typeid(ValueType) == type);
- return *(cast(ValueType*)m_held.ptr);
- }
- public bool empty()
- {
- return m_which < 0;
- }
- public void swap(inout SelfType var)
- {
- Holder h;
- h[] = m_held;
- int w = which;
- m_held[] = var.m_held;
- m_which = var.which;
- var.m_held[] = h;
- var.m_which = w;
- }
- public static SelfType opCall(ValueType)(ValueType val)
- {
- SelfType var;
- var = val;
- return var;
- }
- }
- void main()
- {
- class Foo
- {
- public:
- int n = 0;
- int x = 0;
- int y = 0;
- int z = 0;
- Foo opAssign(int rhs)
- {
- x = rhs;
- y = rhs;
- z = rhs;
- return this;
- }
- }
- struct Bar
- {
- public:
- int x = 0;
- int y = 1;
- int z = 2;
- }
- Variant!(double, int, char[], Foo, Bar) v = 2; // DMD 0.177 new feature
- assert(v == 2);
- assert(v <= 2);
- v = 2.22;
- assert(v == 2.22);
- assert(v.type == typeid(double));
- v = new Foo;
- assert(v.type == typeid(Foo));
- v.get!(Foo)() = 2;
- assert(v.get!(Foo)().z == 2);
- typeof(v) v2 = v;
- assert(v2 == v);
- v = "Foobar".dup;
- assert(v == "Foobar".dup);
- v.swap(v2);
- assert(v2.get!(char[])() == "Foobar");
- Bar b;
- b.x = 10;
- v = b;
- assert(v.get!(Bar)().x == 10);
- }
评论 共 0 条 请登录后发表评论