2015-07-01 105 views
1

編輯:我可以簡化以下模板嗎?

感謝您的優秀答案。我顯然沒有給出我的問題足夠的細節。我試圖糾正這一點,

我更新一些舊代碼,並有幾個重載函數具有以下模式:

void foo (Int bla, const char* bla1, const char* bla2, ...); 
void foo (Int bla, SomeCustomContainer); 

現在,我們正在逐步淘汰的自定義容器,並使用std容器代替。自定義容器的簽名是這樣的,我可以在continainer上進行模板化,重新使用代碼,並同時支持舊代碼和新代碼,直到遺留代碼被淘汰。

我的第一個嘗試是:

template <typename ContainerT> void foo(int bla, ContainerT); 

但是編譯器吐出了一個錯誤,原因是其在爲const char *簽名的模板函數相匹配。

基於StackOverflow上一個答案,我想下面的模板簽名:

template <typename ValT, template <typename, typename = std::allocator<ValT> > 
      class ContainerT> 
void foo(Int bla, const ContainerT<ValT>& rasInParams) 

這解決我的問題 - 編譯器找到正確的過載,一切工作正常,我的目的。我唯一的抱怨是,對於一個對模板不太熟悉的同事來說,這是一個很大的分析,我想知道是否有一種方法可以簡化它 - 我正在考慮使用類型別名,但也許有人知道更好的方法來解決我的基礎重載解決問題?

+0

什麼叫 「更容易閱讀」 期待? – davidhigh

+0

我認爲這兩個答案仍然有效的更新的問題。你所要做的就是向'SomeCustomContainer'類中添加'value_type'類型定義(如果它們不存在的話)(或者你也可以在@ sehe的答案中使用'begin()'開始使用這個技巧) –

+0

@Anton Savin:對不起,我沒有得到你想說的話 - 如果是我當前的解決方案和通過各種定製容器並修改它們(當目標只是將其刪除時)之間的選擇,我更喜歡當前的解決方案。我的問題不是我需要知道值類型,而是編譯器發現錯誤的函數重載(不是模板實現,而是接受char *)。 – Spacemoose

回答

1

你可以簡單的寫(前提是你使用的是標準的容器中,作爲參數):

template <typename ContainerT> 
void foo(const ContainerT& rasInParams) { 
    using ValT = typename ContainerT::value_type; 
    // ... 
} 

如果你想foo不參與重載決議如果參數不是一個容器,可以用SFINAE。這仍然看起來比你原來的代碼更簡單:

template <typename ContainerT, typename = ContainerT::value_type> 
void foo(const ContainerT& rasInParams) 
+0

我認爲你最近的編輯是按照我想要的方向進行的,但是按照書面方式,它不能在我的自定義容器上解析。我不清楚typename = ContainerT :: value_type是幹什麼的。 – Spacemoose

2

的樣品不一般工作(想象,不接受一個allocator,或需要兩個以上的類型參數,或上帝保佑的容器,非類型參數)。

我通常的做法是隻爲了

template <typename Container> 
void foo(const ContainerT& rasInParams) 

如果你需要知道你可以做任何事情一樣

typename Container::value_type 

std::remove_reference<decltype(*rasInParams.begin())>::type 

如果你真的是值類型需要嵌入一個可配置的容器f ROM模板的模板參數,你可以使用一個可變參數簽名嵌套一個:

template<typename ValT, template<T...> class Container> 
void foo() { 
    Container<ValT, std::allocator<ValT> > x; 
} 

另一種選擇是去同一個容器「選擇」元功能。這是例如在Boost圖庫使用:

+0

@davidhigh謝謝,修正 – sehe