5

I tried to write a function to do whatever to a series of data.

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

This function was designed to operate STL containers and it's OK. But I want another version for C-array. So I tried this:

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

I've read "Partial template specialization for arrays"(and several another related post), but it's for class template. And I also know that when you're specializing a function template, you are actually overloading it. Anyway, the solution in that post can't be implemented here.

Any (or maybe no) way could I do this? :-) Thx for tolerating my poor English and thx for your helps.

Community
  • 1
  • 1
sqd
  • 1,485
  • 13
  • 23
  • 2
    Remember that in a parameter declaration, `T[N]` is the same as `T*`. Since the size information is lost, `N` can't be deduced, and so that template is rejected as an overload candidate when its template argument isn't explicitly specified. You can use a reference to satisfy this (`T (&)[N]`) but I would really recommend using iterators to generalize this operation. – David G Oct 06 '14 at 13:28
  • 1
    As well as studying any answers, have a look at `std::for_each` – Bathsheba Oct 06 '14 at 13:29

2 Answers2

5

You miss the reference to array:

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

BTW, in your case, you may simply use (const) reference in the generic case:

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);
}

or even better:

template<typename T>
void foo(T& x){
    for (auto&& e : x)
        do_something(x);
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
5

You could pass it by reference :

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

But the true solution to your problem is to pass a pair of iterators to a single function template (working for both arrays and standard containers) :

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));
}
quantdev
  • 23,517
  • 5
  • 55
  • 88
  • 1
    +1 Its worth nothing that the single-param interface is still possible even with an iterator-based solution by providing overloads. I.e. the `T (&ar)[N]` overload can simply invoke `foo(std::begin(ar), std::end(ar))`. A similar overload can be provided for generic container enumeration via a variadic template-template overload. And both will most-assuredly be inlined to a near-no-op in released-code. – WhozCraig Oct 06 '14 at 13:35