`
oldrev
  • 浏览: 229686 次
  • 性别: Icon_minigender_1
  • 来自: 昆明
社区版块
存档分类
最新评论

port boost.variant to D

阅读更多
今晚无聊,完整用D实现了Boost.Variant 的绝大部分,权当娱乐了。


1 // Module: variant.d
2 // Author: Oldrev (wstring#AT#gmail.com)
3 // License: BSD
4
5 module dust.meta.variant;
6
7 import std.typetuple;
8 import std.traits;
9
10 private template MaxSizeImp(T, V...)
11 {
12 static if(V.length > 0)
13 private const int tailResult = MaxSizeImp!(V).result;
14 else
15 private const int tailResult = T.sizeof;
16
17 public const int result = T.sizeof > tailResult ? T.sizeof : tailResult;
18 };
19
20 template MaxSize(TList...)
21 {
22 const int MaxSize = MaxSizeImp!(TList).result;
23 }
24
25 struct Variant(TList...)
26 {
27 public alias TList TypeList;
28 public alias Variant!(TypeList) SelfType;
29 private alias ubyte[MaxSize!(TypeList)] Holder;
30
31 private Holder m_held;
32 private int m_which = -1;
33
34 public int which()
35 {
36 return m_which;
37 }
38
39 public SelfType assign(ValueType)(ValueType val)
40 {
41 static if(is(ValueType == SelfType))
42 {
43 foreach(T; TypeList)
44 {
45 const int i = IndexOf!(T, TypeList);
46 if(val.which == i)
47 {
48 assign!(T)(val.get!(T));
49 m_which = i;
50 }
51 }
52 }
53 else
54 {
55 const int i = IndexOf!(ValueType, TypeList);
56 static assert(i >= 0);
57 ValueType* heldPtr = cast(ValueType*)m_held.ptr;
58 *heldPtr = val;
59 m_which = i;
60 }
61
62 return *this;
63 }
64
65 public SelfType opAssign(ValueType)(ValueType rhs)
66 {
67 return assign!(ValueType)(rhs);
68 }
69
70 public bool opEquals(ValueType)(ValueType rhs)
71 {
72 static if(is(ValueType == SelfType))
73 {
74 foreach(T; TypeList)
75 {
76 const int i = IndexOf!(T, TypeList);
77 if(i == which)
78 {
79 return (rhs.which == which) && (get!(T) == rhs.get!(T));
80 }
81 }
82 }
83 else
84 {
85 const int i = IndexOf!(ValueType, TypeList);
86 static assert(i >= 0);
87
88 ValueType* heldPtr = cast(ValueType*)m_held.ptr;
89 return *heldPtr == rhs;
90 }
91 }
92
93 public int opCmp(ValueType)(ValueType rhs)
94 {
95 if(rhs == *this)return 0;
96 static if(is(ValueType == SelfType))
97 {
98 foreach(T; TypeList)
99 {
100 const int i = IndexOf!(T, TypeList);
101 if((i == which) && (rhs.which == which))
102 {
103 return get!(T) < rhs.get!(T) ? -1 : 1;
104 }
105 }
106 }
107 else
108 {
109 const int i = IndexOf!(ValueType, TypeList);
110 static assert(i >= 0);
111
112 ValueType* heldPtr = cast(ValueType*)m_held.ptr;
113 return *heldPtr < rhs ? -1 : 1;
114 }
115 }
116
117 public TypeInfo type()
118 {
119 foreach(T; TypeList)
120 {
121 const int i = IndexOf!(T, TypeList);
122 if(i == which)
123 {
124 return typeid(TypeList[i]);
125 }
126 }
127 }
128
129 public ValueType get(ValueType)()
130 {
131 return *(cast(ValueType*)m_held.ptr);
132 }
133
134 public bool empty()
135 {
136 return m_which < 0;
137 }
138
139 public bool isKindOf(ValueType)(ValueType val)
140 {
141 const int i = IndexOf!(ValueType, TypeList);
142 static assert(i >= 0);
143 return which == i;
144 }
145
146 }
147
148 unittest
149 {
150 class Foo
151 {
152 public:
153 int n = 0;
154 int x = 0;
155 int y = 0;
156 int z = 0;
157
158 Foo opAssign(int rhs)
159 {
160 z = rhs;
161 return this;
162 }
163 }
164
165 Variant!(double, char, int, char[], Foo) v;
166 v = 2;
167 assert(v == 2);
168 v = 2.22;
169 assert(v == 2.22);
170 assert(v.type == typeid(double));
171 v = new Foo;
172 assert(v.type == typeid(Foo));
173 v.get!(Foo)() = 2;
174 assert(v.get!(Foo)().z == 2);
175 typeof(v) v2 = v;
176 assert(v2 == v);
177 assert(v <= 2);
178 v = cast(char[])"Foobar";
179 assert(v == cast(char[])"Foobar");
180
181 }
分享到:
评论
1 楼 oldrev 2007-04-24  
1.013 终极版:

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;
}


/**
  \brief A Variant implemention inspired by boost.variant
*/
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;

	template Which(T)
	{
		const int Which = IndexOf!(T, TypeList);
	}

    public static SelfType opCall(ValueType)(ValueType val)
    {
        SelfType var;
        var = val;
        return var;
    }

    public int which()
    {
        return m_which;
    }

	public SelfType opAssign(ValueType)(ValueType val)
	{
		static if(is(ValueType == SelfType))
		{
			m_held[] = val.m_held[];
			m_which = val.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 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) //used for hash or something else
	out(result)
	{
		assert(result == 0 || result == 1 || result == -1);
	}
	body
	{
		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(IndexOf!(ValueType, TypeList) == which) ;

        return *(cast(ValueType*)m_held.ptr);
    }

    public bool empty()
    {
        return m_which < 0;
    }

	public void swap(ref 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;
	}

}

相关推荐

    浅析C++中boost.variant的几种访问方法

    Boost.Variant Variant库包含一个不同于union的泛型类,用于在存储和操作来自于不同类型的对象。这个库的一个特点是支持类型安全的访问,减少了不同数据类型的类型转换代码的共同问题。 Variant 库如何改进你的程序...

    THE BOOST C++ LIBRARIES

    THE BOOST C++ LIBRARIES是一份自己编译的chm格式文档,描述了...14.4 Boost.Variant 14.5 Exercises Chapter 15: Error Handling 15.1 General 15.2 Boost.System 15.3 Boost.Exception Chapter 16: Cast Operators

    variant, Eggs.Variant 是 C 11/14/17 泛型,类型安全,可以识别的联合.zip

    variant, Eggs.Variant 是 C 11/14/17 泛型,类型安全,可以识别的联合 Eggs.Variant简介英镑 Eggs.Variant 为英镑 C 11/14/17 型,类型安全,可以区分。 参见 http://eggs-cpp.github.io/variant/的文档。要求库...

    json序列化的库Kapok.zip

    kapok是一个高性能跨平台的对象-json序列化的库,对象序列化后是标准的... kapok除了支持结构体、容器和数组之外,还支持boost.optional和boost.variant,使用起来非常方便。 详细信息请看这里。 标签:Kapok

    java-jacob 打印

    The package names replace com.ms with com.jacob (for example com.ms.com.Variant maps to com.jacob.com.Variant. jacob.dll: a small Win32 DLL which you must add to your PATH. samples: provided in ...

    java 操作jacob 生成word,html或者excel

    The package names replace com.ms with com.jacob (for example com.ms.com.Variant maps to com.jacob.com.Variant.  jacob.dll: a small Win32 DLL which you must add to your PATH.  samples: provided in...

    linux下编译boost.python简单方法

    最近项目使用c++操作Python脚本,选用boost.python库。在window下编译安装很顺利,但是在Linux下一直编译不通过,总是提示找不到头文件。..../bjam --build-type=minimal --with-python variant=release link=static

    c++ 17 ' std::variant ' for c++ 11/14/17

    :variant for C++11/14/17.Based on Continuously tested against libc++'s std::variant test suite.DocumentationIntegrationSingle HeaderThe branch provides a standalone variant.hppfile for each .Copy it ...

    java操作word(内部资料).doc

    The package names replace com.ms with com.jacob (for example com.ms.com.Variant maps to com.jacob.com.Variant.  jacob.dll: a small Win32 DLL which you must add to your PATH.  samples: provided in ...

    json.hpp:使用Boost.Spirit的小型C ++ JSON解析库

    我的主要目标只是在实际用例中试用Spirit,并能够尽可能轻松地将JSON解析为boost::variant 。 用法 解析JSON: # include # include int main () { using boost::get; std::string json_string{ " { \" names...

    Boost C++ Libraries 1.63.0,Windows + MinGW 编译

    Boost编译指令:b2.exe --build-type=complete toolset=gcc variant=release link=static threading=multi runtime-link=static install 对于QT使用,已经写好一个 boost.pri 文件放在Boost目录下,只需要在 *.pro ...

    iniphile:C++的ini文件解析库

    英尼菲尔 C++的ini文件解析库 作者: 罗曼·纽豪瑟 接触: ... 接口提到了Boost.Optional [2]和Boost.Variant [3] ,最突出的实现细节是Boost.Spirit [4] ,特别是 v2.1 ( Boost [1] 1.41) 或更高版

    zehon_transfer_pack-1.1_jdk14

    SCP – a variant of BSD rcp utility that transfers files over SSH session. The SCP protocol has been mostly superseded by the more comprehensive SFTP protocol and some implementations of the "scp" ...

    libraries:ASL库将在stlab命名空间中迁移到此处,新库将在此处创建

    支持平台所有具有C ++ 14兼容编译器的操作系统要求C ++ 14编译器-Visual Studio 2017(&gt; = 15.9.0),Visual Studio 2019-gcc(&gt; = 7)-clang(&gt; = 6) 如果编译器的库未提供boost.optional和boost.variant boost....

    purescript-variant, PureScript的多态变体.zip

    purescript-variant, PureScript的多态变体 purescript变体 PureScript的多态变体。安装bower install purescript-variant文档模块文档是发布时的发布。Data.Variant 是PureScr

    用于控制 Bosch Sensortec 的 BMI08x 系列 IMU 的传感器API_C语言_代码_相关文件_下载

    dev.variant = BMI085_VARIANT; 将 bmi08x_dev 的变体更新为 BMI088_VARIANT 以使用 BMI085 传感器功能 dev.variant = BMI088_VARIANT; 用户必须在代码中包含bmi08x.h才能调用传感器 API,如下所示: #include ...

    C语言头文件 VARIANT

    C语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言头文件 VARIANTC语言...

    AltiumDesigner20装配变量Variant使用说明 .pdf

    AltiumDesigner20装配变量Variant使用说明 .pdf

    byte-VARIANT.rar_VARIANT byte_com variant BYT_variant_visual c_字

    这段程序可以把byte[](字节数组)转换为VARIANT类型。

Global site tag (gtag.js) - Google Analytics