原创作者: 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 代码
 
  1. // Module:  variant.d  
  2. // Author:  Oldrev (wstring#AT#gmail.com)  
  3. // License: BSD  
  4.   
  5. module variant;  
  6.   
  7. import std.typetuple;  
  8. import std.traits;  
  9. import std.stdio;  
  10.   
  11. private template MaxSizeImp(T, V...)  
  12. {  
  13.     static if(V.length > 0)  
  14.         private const int tailResult = MaxSizeImp!(V).result;  
  15.     else   
  16.         private const int tailResult = T.sizeof;  
  17.   
  18.     public const int result = T.sizeof > tailResult ? T.sizeof : tailResult;  
  19. };  
  20.   
  21. private template MaxSize(TList...)  
  22. {  
  23.     const int MaxSize = MaxSizeImp!(TList).result;  
  24. }  
  25.   
  26. struct Variant(TList...)  
  27. {  
  28.     public alias TList TypeList;  
  29.     public alias Variant!(TypeList) SelfType;  
  30.     private alias ubyte[MaxSize!(TypeList)] Holder;  
  31.   
  32.     private Holder  m_held;  
  33.     private int     m_which = -1;  
  34.   
  35.     public int which()  
  36.     {  
  37.         return m_which;  
  38.     }  
  39.   
  40.     public SelfType assign(ValueType)(ValueType val)  
  41.     {  
  42.         static if(is(ValueType == SelfType))  
  43.         { 
  44.             m_held[] = val.m_held[];
  45.             m_which = which;
  46.         }         
  47.         else  
  48.         {  
  49.             const int i = IndexOf!(ValueType, TypeList);  
  50.             static assert(i >= 0);  
  51.             ValueType* heldPtr = cast(ValueType*)m_held.ptr;  
  52.             *heldPtr = val;  
  53.             m_which = i;  
  54.         }  
  55.   
  56.         return *this;  
  57.     }  
  58.   
  59.     public SelfType opAssign(ValueType)(ValueType rhs)  
  60.     {  
  61.         return assign!(ValueType)(rhs);  
  62.     }  
  63.   
  64.     public bool opEquals(ValueType)(ValueType rhs)  
  65.     {  
  66.         assert(!empty);  
  67.   
  68.         static if(is(ValueType == SelfType))  
  69.         {  
  70.             foreach(T; TypeList)  
  71.             {  
  72.                 const int i = IndexOf!(T, TypeList);  
  73.                 if(i == which)  
  74.                 {  
  75.                     return (rhs.which == which) && (get!(T) == rhs.get!(T));  
  76.                 }  
  77.             }  
  78.         }  
  79.         else  
  80.         {  
  81.             const int i = IndexOf!(ValueType, TypeList);  
  82.             static assert(i >= 0);  
  83.           
  84.             return get!(ValueType)() == rhs;  
  85.         }  
  86.     }  
  87.   
  88.     public int opCmp(ValueType)(ValueType rhs)  
  89.     {  
  90.         if(rhs == *this)return 0;  
  91.         static if(is(ValueType == SelfType))  
  92.         {  
  93.             foreach(T; TypeList)  
  94.             {  
  95.                 const int i = IndexOf!(T, TypeList);  
  96.                 if((i == which) && (rhs.which == which))  
  97.                 {  
  98.                     return get!(T) < rhs.get!(T) ? -1 : 1;  
  99.                 }  
  100.             }  
  101.         }  
  102.         else  
  103.         {  
  104.             const int i = IndexOf!(ValueType, TypeList);  
  105.             static assert(i >= 0);  
  106.           
  107.             return get!(ValueType)() < rhs ? -1 : 1;  
  108.         }  
  109.     }  
  110.       
  111.     public TypeInfo type()  
  112.     {  
  113.         foreach(T; TypeList)  
  114.         {  
  115.             const int i = IndexOf!(T, TypeList);  
  116.             if(i == which)  
  117.             {  
  118.                 return typeid(TypeList[i]);  
  119.             }  
  120.         }  
  121.     }  
  122.   
  123.     public ValueType get(ValueType)()  
  124.     {  
  125.         assert(typeid(ValueType) == type);  
  126.         return *(cast(ValueType*)m_held.ptr);  
  127.     }  
  128.   
  129.     public bool empty()  
  130.     {  
  131.         return m_which < 0;  
  132.     }  
  133.   
  134.     public void swap(inout SelfType var)  
  135.     {  
  136.         Holder h;  
  137.         h[] = m_held;  
  138.         int w = which;  
  139.         m_held[] = var.m_held;  
  140.         m_which = var.which;  
  141.         var.m_held[] = h;  
  142.         var.m_which = w;  
  143.     }  
  144.   
  145.     public static SelfType opCall(ValueType)(ValueType val)  
  146.     {  
  147.         SelfType var;  
  148.         var = val;  
  149.         return var;  
  150.     }  
  151.   
  152. }  
  153.   
  154. void main()  
  155. {  
  156.     class Foo  
  157.     {  
  158.         public:  
  159.         int n = 0;  
  160.         int x = 0;  
  161.         int y = 0;  
  162.         int z = 0;  
  163.   
  164.         Foo opAssign(int rhs)  
  165.         {  
  166.             x = rhs;  
  167.             y = rhs;  
  168.             z = rhs;  
  169.             return this;  
  170.         }  
  171.     }  
  172.   
  173.     struct Bar  
  174.     {  
  175.         public:  
  176.         int x = 0;  
  177.         int y = 1;  
  178.         int z = 2;  
  179.     }  
  180.   
  181.     Variant!(doubleintchar[], Foo, Bar) v = 2; // DMD 0.177 new feature  
  182.     assert(v == 2);  
  183.     assert(v <= 2);  
  184.     v = 2.22;  
  185.     assert(v == 2.22);  
  186.     assert(v.type == typeid(double));  
  187.     v = new Foo;  
  188.     assert(v.type == typeid(Foo));  
  189.     v.get!(Foo)() = 2;  
  190.     assert(v.get!(Foo)().z == 2);  
  191.     typeof(v) v2 = v;  
  192.     assert(v2 == v);  
  193.     v = "Foobar".dup;  
  194.     assert(v == "Foobar".dup);  
  195.       
  196.     v.swap(v2);  
  197.     assert(v2.get!(char[])() == "Foobar");  
  198.       
  199.     Bar b;  
  200.     b.x = 10;  
  201.     v = b;  
  202.     assert(v.get!(Bar)().x == 10);  
  203.   
  204. }  
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

文章信息

  • qiezi在2007-03-07创建
  • qiezi在2011-05-26更新
Global site tag (gtag.js) - Google Analytics