2010-06-14 92 views
3

我想每個人都有經驗,類似下面的代碼工作:如何使用重載函數作爲函數模板的參數?

void fun(Type1&); 
void fun(Type2&); 
vector<Type1> vec; 
for_each(vec.begin(), vec.end(), fun); 

當然不會編譯,因爲目前還不清楚其功能是傳遞。什麼是您常用的解決方案?

我知道這將工作:

for_each(vec.begin(), vec.end(), (void(*)(Type1&))fun); 

但是,任何更好的想法?

回答

2

一種解決方案是使用模板函數:

template<typename T> 
void fun(T&); 
// specialize fun for Type1 and Type2 
... 
for_each(vec.begin(), vec.end(), fun<Type1>); 

更好的辦法是使用仿函數與模板operator()

struct fun 
{ 
    template<typename T> 
    void operator()(T&) const; 
}; 
... 
for_each(vec.begin(), vec.end(), fun()); // T for operator() will be deduced automatically 
0

我想第二基里爾的答案。如果fun()函數的實現非常相似(涉及不同類型的相同代碼),將它們重寫爲一個單一模板函數是一個好主意。作爲一個額外的補充,你可以優雅地指定你需要的功能。

它通常建議使用C++相當於C風格的類型轉換:

for_each(vec.begin(), vec.end(), reinterpret_cast<void(*)(Type1&)>(fun)); 

更合適的是在這種情況下使用的static_cast:

for_each(vec.begin(), vec.end(), static_cast<void(*)(Type1&)>(fun)); 

,因爲我們要提示編譯器到正確的類型。

儘管更冗長,但最好僅僅出於代碼維護的原因 - 在代碼中搜索此類構造比在C風格類型轉換中更容易。

還有一種可能性,以避免使用類型轉換有利於明確的模板參數規格:

for_each<std::vector<A>::iterator, void(*)(Type1&)>(vec.begin(), vec.end(), fun); 

- 雖然它不是從原來的代碼非常大的提升。正如你所看到的,你也必須明確指定第一個模板參數。

+0

那麼......它仍然是類型鑄造。 其實我在另一個網站上看到這個問題。除了類型鑄造,我沒有提出一個好的解決方案。所以我想看看是否有真正的優雅方法來做到這一點。 但是,在這種情況下,我總是喜歡函數對象或lambda expr。 :) – hpsMouse 2010-06-16 04:33:11