d的类型元组
import std.typetuple;
alias list = TypeTuple!(AA, AB, AC);
但是,不能在运行时像数组一样索引它;尝试newlist[n]将是编译时错误.相反,创建辅助函数来循环它并返回实例,如下所示:
foreach(index, type; list)
if(index == testv) {
a = new type();
break;
}
展开
foreach(foo; compile_time_list)
就像:
if(0 == testv) { a = new AA(); goto end; }
if(1 == testv) { a = new AB(); goto end; }
if(2 == testv) { a = new AC(); goto end; }
end:
因此,适用于运行时值,帮助绑定编译时列表和数组索引.
注意,并非最有效,另一个提高速度选择是在编译时从列表中生成switch语句,然后插件它.将编译switch语句为更有效的查找表.但也许简单循环也很好.
无论如何,把它放在一起,得到:
import std.stdio;
interface A {}
class AA: A {}
class AB: A {}
class AC: A {}
import std.typetuple;
alias list = TypeTuple!(AA, AB, AC);
void testf(ulong testv) {
A a;
foreach(index, type; list)
if(index == testv) {
a = new type();
break;
}
if(a is null)
writeln("坏索引");
else {
writeln("创建了",typeid(cast(Object) a));
}
}
void main() {
testf(0);
testf(1);
testf(2);
testf(3);
}
//结果
$ ./test50
创建了test50.AA
创建了test50.AB
创建了test50.AC
坏索引
typeid(cast(Object)a)可能看起来很奇怪,那是获取类型的动态类.它必须首先转换为Object,否则它将打印接口名称.由于D接口不一定是D类(它们也可以是COM对象或C++类),因此typeid并不总是可用的.转换为Object确保它是D类,从而获取运行时类型的详细信息.
检查循环中的基类
可以为它编写自己的元组模板,或者只是让工厂函数上的编译失败:A a=new T();如果A不是T的基类或接口,则会失败.
bool checkClassList(Base, T...)() {
foreach(t; T) {
static if(!is(t : Base))
static assert(0, t.stringof ~ "不是..的子类" ~ Base.stringof);
}
return true;
}
template ClassList(Base, T...) if(checkClassList!(Base, T)) {
alias ClassList = T;
}
用法:
alias list = ClassList!(A, AA, AB, AC);
//正确
class B {}
alias list = ClassList!(A, AA, AB, AC, B);
//错误.
浙公网安备 33010602011771号