2016-07-04 62 views
2

我正在閱讀有關語言vala的內容,並將其編譯爲Ansi C代碼。不過,我也看到它支持像Java或Rust這樣的泛型。現在我的問題是這是如何編譯爲C代碼?如果我有一個泛型類或函數,會生成什麼樣的C代碼來模擬泛型行爲?Vala泛型轉換爲C代碼

+0

說你寫一個通用的'名單'然後其他編程語言使用'list '和'list '。 Vala編譯器將編寫具有適當行爲的C結構list_int和list_double。換句話說,實例化一個特定的泛型的工作是由Vala完成的。 – nwp

+1

這不會和C++模板一樣嗎?但模板並不像我想的泛型一樣。 – Exagon

+0

C++模板的行爲與C#泛型相似(如[在此解釋](http://stackoverflow.com/a/31929/69809))。這與vala泛型將爲您傳遞的每個通用參數創建實際結構是一樣的。 – Groo

回答

5

Vala泛型基於gpointerGType

您只能使用基於指針的類型參數來專門化Generic類。

class MyClass<T> { 

public T val; 

} 

public static int main (string[] args) { 
    // This wouldn't compile! 
    // var il = new Gee.ArrayList<int>(); 

    var il = new Gee.ArrayList<int?>(); 
    var dl = new Gee.ArrayList<double?>(); 
    il.add (5); 
    dl.add (3.0); 

    var im = new MyClass<int?>(); 
    im.val = 5; 

    var dm = new MyClass<double?>(); 
    dm.val = 3.0; 

    var lm = new MyClass< Gee.List<int?> >(); 
    lm.val = il; 

    return 0; 
} 

您可以檢查自己生成的代碼與-C參數:

valac -C Main.vala --pkg gee-0.8 

這將產生一個main.c文件。如果仔細閱讀,您將看到My​​Class只有一個結構(加上一些額外的輔助結構,它們是基於GObject的類所需的),它具有成員gpointer val,它也有一個GType t_type以及一個t_dup_func和一個t_destroy_func

struct _MyClass { 
     // ... 
     gpointer val; 
}; 

struct _MyClassPrivate { 
     GType t_type; 
     GBoxedCopyFunc t_dup_func; 
     GDestroyNotify t_destroy_func; 
}; 

確保正確的類型通過GLib type checking被執行。這使得Vala泛型類型安全(部分在編譯時和部分在運行時)。

這與在編譯時展開的C++模板形成鮮明對比。所以它比C#泛型更接近於傳統的C++模板。

我寫了「部分在編譯時」,因爲Vala編譯器足夠聰明,可以在C代碼中省略類型檢查,因爲它知道賦值總是正確的。

而且瓦拉生成的C代碼,就是要容易的使用對於具有GLib的綁定(如C,Python和C++,GJS等)