2014-10-06 151 views
3

我试图编写一个函数来对一系列数据做任何事情。C++:数组函数模板专门化

//For stl containers 
template<typename T> 
void foo(T x){ 
    for(auto iter=x.begin();iter!=x.end();++iter) 
     do_something(*iter); 
} 

此功能被设计用来操作STL容器,并且没问题。但是我想要C-array的另一个版本。所以,我想这一点:

//For C-array 
template<typename T,size_t N> 
void foo(T x[N]){ 
    //blabla 
} 
//Error 

我读过"Partial template specialization for arrays"(和一些其他相关文章),但它是类模板。而且我也知道,当你专门研究一个函数模板时,你实际上是在重载它。无论如何,该帖子中的解决方案无法在这里实现。

任何(或可能没有)方式我可以这样做吗? :-) Thx为容忍我可怜的英语和thx为您的帮助。

+2

请记住,在参数声明,'T [N]'和'T *'是一样的。由于尺寸信息丢失,无法推导出“N”,因此当其模板参数未明确指定时,模板将作为超载候选项被拒绝。你可以使用引用来满足这个('T(&)[N]'),但我真的推荐使用迭代器来推广这个操作。 – 0x499602D2 2014-10-06 13:28:47

+1

除了学习任何答案外,还要看看'std :: for_each' – Bathsheba 2014-10-06 13:29:48

回答

5

你错过了引用数组:

template<typename T, size_t N> 
void foo(T (&x)[N]){ 
    //blabla 
} 

顺便说一句,你的情况,你可以简单地使用在一般情况下(const)参考:

template<typename T> 
void foo(T& x){ 
    using std::begin; 
    using std::end; 

    for (auto iter = begin(x); iter != end(x); ++iter) 
     do_something(*iter); 
} 

甚至更​​好:

template<typename T> 
void foo(T& x){ 
    for (auto&& e : x) 
     do_something(x); 
} 
5

您可以通过引用的方式将其传递给:

template<typename T,size_t N> 
void foo(T (&x)[N]){ 
    //blabla 
} 

真正解决问题的方法是一对迭代器传递给函数模板(用于阵列和标准集装箱的工作):

template<typename Iterator> 
void foo(Iterator begin, Iterator end){ 
    for(auto it = begin; it!=end; ++it) 
     do_something(*it); 
} 
int main() 
{ 
    int a[] = {1, 2, 3, 4, 5}; 
    foo(std::begin(a) , std::end(a)); 

    std::vector<int> v = {1, 2, 3, 4, 5}; 
    foo(std::begin(v) , std::end(v)); 
} 
+1

+1即使使用基于迭代器的解决方案,通过提供重载,单参数接口仍然是可能的。即'T(&ar)[N]'重载可以简单地调用'foo(std :: begin(ar),std :: end(ar))'。可以通过可变参数模板模板重载为泛型容器枚举提供类似的重载。而且,这两种方式都可以确保在发布代码中被内联到近乎不用的操作。 – WhozCraig 2014-10-06 13:35:10