2013-11-20 44 views
1

我可以在D中創建類數組嗎?就像:D類中的類Array

interface A {} 
class AA: A {} 
class AB: A {} 
class AC: A {} 

ClassList!A list = new ClassList!A {AA, AB, AC}; 

void testf(ulong testv) { 
    A a = new list[testv]; 
} 

回答

3

是的,這是可能的,但不一定完全如何你有它。你可以創建一個類型爲元組的類型列表:

import std.typetuple; 
alias list = TypeTuple!(AA, AB, AC); 

但是,你不能在運行時將它索引爲一個數組;嘗試new list[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("bad type index"); 
    else { 
     writeln(typeid(cast(Object) a), " was created"); 
    } 
} 

void main() { 
    testf(0); 
    testf(1); 
    testf(2); 
    testf(3); 
} 

結果:

$ ./test50 
test50.AA was created 
test50.AB was created 
test50.AC was created 
bad type index 

正是我們想要的。

順便說一句,typeid(cast(Object) a)可能看起來很奇怪,那就是獲取類型的動態類。它必須首先投射到Object,因爲否則它會打印界面名稱。由於D接口不一定是D類(它們也可以是COM對象或C++類),所以typeid並不總是可用的。強制轉換爲對象可確保它是D類,從而獲取運行時類型的詳細信息。

編輯:我看到你問新聞組以及檢查循環中的基類。下面是如何做到這一點:

你可以爲它編寫自己的元組模板,或者讓 編譯在工廠函數上失敗:A a = new T();將 失敗,如果A是不是T.

基類或接口把檢查列表看起來是這樣的:

bool checkClassList(Base, T...)() { 
    foreach(t; T) { 
    static if(!is(t : Base)) 
     static assert(0, t.stringof ~ " is not a child of " ~ Base.stringof); 
    } 
    return true; 
} 

template ClassList(Base, T...) if(checkClassList!(Base, T)) { 
    alias ClassList = T; 
} 

用法:

alias list = ClassList!(A, AA, AB, AC); // good 

地址:

class B {} 
alias list = ClassList!(A, AA, AB, AC, B); 

並獲取錯誤:

test50.d(12): Error: static assert "B is not a child of A" 
test50.d(19):  instantiated from here: checkClassList!(A, AA, AB, AC, B)