2010-06-14 66 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