2013-07-12 100 views
5

我使用xsd從xml模式文件創建C++代碼。對於一個xml類型,創建多個函數(用於序列化等)。
如果類型被稱爲XmlType將創建下列形式的多種功能:具有相同名稱但參數類型不同的多個函數作爲模板參數

XmlType XmlType_(const XmlType& a, const string& b) 
string XmlType_(const XmlType& a) 
... 

這是正常的功能,而不是XmlType將的成員,它們都具有相同的名稱。 對於XmlType2該功能將被稱爲XmlType2_

我想爲我的xml方案的所有不同的xml類型編寫一個實用程序模板類。不同的功能將被稱爲洞察這個類。我到目前爲止是這樣的:

XmlUtil<XmlType, XmlType_, XmlType_> util; 

這感覺有點多餘的,會變得更糟:

template<typename T> 
using TFunc1 = T (*)(const T&, const string&); 
template<typename T> 
using TFunc2 = string (*)(const T&); 

template<typename T, TFunc1<T> func2, TFunc2<T> func2> 
class XmlUtil { 
... 
}; 

當如果必須這樣做,這樣創建XmlUtil類的一個實例,當我必須通過更多的功能作爲參數。

我想使用的Util類是這樣的:

XmlUtil<XmlType, XmlType_> util; 

甚至更​​好這樣

XmlUtil<XmlType> util; 

我能想到的就是以某種方式使用所定義的唯一途徑,但它不感覺不錯。
有沒有其他的方法來做到這一點?

編輯: 我現在使用一個定義:

#define TRPL(name) name, name ## _, name ## _ 
... 
XmlUtil<TRPL(XmlType)> util; 

我將修改這一點,如果我找到一個更好的(也許覆蓋套像Yakk在他的回答提出)。

+0

這是C++ 11特有的,我相信嗎? –

+0

是的,我使用的是C++ 11(MinGW和gcc 4.8)。添加了標籤。 – guini

+0

模板專業化。在C++中使用它進行等效的Func <>(在c#中),其中Execute具有模板參數特定實現和參數計數。通過使用模板中的默認設置,您可以選擇僅定義一些類型參數。 –

回答

3

此:

XmlUtil<XmlType> util; 

是不可能的,因爲沒有辦法擺脫XmlTypeXmlType_。在自動代碼生成器之後它們的關係被丟棄。

然而這樣的:

XmlUtil<XmlType_> util; 

是可能的。您可以推導出XmlType_的函數類型,然後使用推導的返回類型,即XmlType。我相信有這個目的的標準庫函數。

對於兩個不同的過載,這可能是棘手。我不認爲你可以傳遞一個函數重載集合作爲模板參數,解析是在模板參數的上下文中對一個函數的模板參數完成的。如果不使用預處理器,我認爲沒有辦法推遲這個操作。

所以我認爲你應該使用#define。這總比沒有好。

0

類定義中的默認模板參數?

template<typename T, TFunc1<T> func1 = XmlType_, TFunc2<T> func2 = XmlType_> 
class XmlUtil { 
    // ... 
}; 
+0

函數的名稱取決於類型名稱。所以我認爲這是行不通的。我編輯了這個問題,使之更清晰。 – guini

+1

@guini我只是試了一下,[它似乎編譯正常](http://ideone.com/fu5s8M)。值得一試? –

+0

如果我理解正確,函數名稱XmlType_在您的示例中已修復。但在我的情況下,函數名稱會改變。如果我有類型Type1,函數將被稱爲Type1_,對於Type2它將被稱爲Type2_等。 – guini

0

您可以使用一個特質類這樣

template <typename T> 
struct Trait{ 
    typedef T type; 
    typedef T (*func1)(const T&, const string&); 
    typedef string (*func2)(const T&); 
}; 

,使類XmlUtil有一個模板參數(我們將其命名爲性狀),並使用特質::類型,特質:: func1和Trait :: func2。完整使用請參見here

在這個例子中,XmlUtil的類型是這樣:

XmlUtil<Trait<XmlType> > 

我已經這樣做了,因爲我不熟悉你的問題。這可能是你可以定義特質類右轉入XmlUtil和使用

XmlUtil<XmlType> 

其他變化是可能的,它只是取決於你需要什麼樣的情況。

你可以閱讀一個非常簡短的介紹特質類​​。如果你想閱讀更多關於這個話題,我建議你現代C++(Alexandrescu)。

+0

感謝您的回答。我會檢查出來的。但我需要一些時間來了解它:-) – guini

+0

我改變了代碼鏈接,我在那裏寫了一些評論 –

+0

重新閱讀問題和答案我不確定我是否正確地解決了您的問題,請給我一些反饋意見如果需要,我可以提供更多的幫助。 –

0

我不知道我完全理解你的要求。序列化和反序列化的常用方法是創建工廠(抽象工廠)並動態地解析對象的構造。請注意,對於複雜結構,這可以得到改進,其中代碼生成器可以創建成員函數來提取每個成員的確切類型。

但同樣,我不完全理解你真正想做...作爲一個建議,我相信,如果你提供了更多的解決問題的說明,它會有所幫助,因爲這個問題集中在如何讓你的解決方案發揮作用,並隱含地拋棄其他可能更好的設計方法。

1

這看起來像是覆蓋集的作業。 foo_override_set_type類型的

static struct foo_override_set_type { 
    template<typename... Args> 
    auto operator()(Args...&& args) const 
    -> 
    decltype(foo(std::forward<Args>(args)...)) 
    { return (foo(std::forward<Args>(args)...)); } 
    template<typename T> 
    operator T() { return foo; } 
} foo_override_set; 

對象代表整個手柄組foo的。使用operator()調用它們會對foo執行覆蓋設置查找並調用結果函數。將它們轉換爲函數指針與將代碼foo轉換爲函數指針(或其他值)的做法相同。

你的代碼生成可以自動生成這樣的覆寫集類型。它還可以製作一個特徵類,通過專業化從XmlType類型映射到覆蓋集XmlType_函數。

然後,您的XmlUtil<XmlType>可以通過該特徵類訪問覆蓋集XmlType_。它首先實例化override設置變量,然後調用()

另外,@Xeo有一個建議,即創建這樣的對象,就像在C++ 1y或C++ 1z中輸入[]XmlType_一樣簡單。

+0

感謝您的建議。我還沒有完全理解它,但我會研究它。你可能有一個關於覆蓋集的文檔的鏈接? – guini

+1

@guini不,不是真的。覆蓋集只是一個對象,它的行爲「好像」是一個語法上某個函數名稱的完全重寫集合。你可以用完美的轉發和一個'template operator T'來做到這一點。你可以閱讀完美的轉發(我在上面的'operator()'中使用的C++ 11技術),這可以使它更有意義。 'operator T'存在,所以你可以給函數指針分配一個覆蓋集,並讓它「神奇地」提取屬性覆蓋。而且因爲它是一個無狀態的對象,所以可以將它或它的類型傳遞到你需要的地方。 – Yakk

相關問題