Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing an array by reference to template function in c++

Tags:

c++

templates

The below code just works fine for me.

#include <iostream>
using namespace std;

template<class T>
T sum_array(T (&a)[10], int size)
{
    T result=0;
    for(int i=0; i<size; i++)
    {
        result = a[i] + result;
    }
    return result;
}

int main()
{
    int a[10] = {0,1,2,3,4,5,6,7,8,9};
    cout<<sum_array(a, 10)<<endl;
    double d[10] = {1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1};
    cout<<sum_array(d, 10)<<endl;
    cin.get();
}

But if try to make my function more generic by removing the array size as shown below in function it gives a error saying no instance of function template.

template<class T>
T sum_array(T (&a)[], int size)
{
    T result=0;
    for(int i=0; i<size; i++)
    {
        result = a[i] + result;
    }
    return result;
}

At the same time if i remove the reference as shown below it just works fine.

template<class T>
T sum_array(T a[], int size)
{
    T result=0;
    for(int i=0; i<size; i++)
    {
        result = a[i] + result;
    }
    return result;
}

I am relatively new to templates can you please explain the above behavior.

like image 754
Naveen Avatar asked Nov 23 '13 14:11

Naveen


People also ask

Can you pass an array by reference in C?

An array can be passed to functions in C using pointers by passing reference to the base address of the array, and similarly, a multidimensional array can also be passed to functions in C.

Can you pass arrays by reference?

Arrays can be passed by reference OR by degrading to a pointer. For example, using char arr[1]; foo(char arr[]). , arr degrades to a pointer; while using char arr[1]; foo(char (&arr)[1]) , arr is passed as a reference.

How an array is passed to a function in C language?

How Arrays are Passed to Functions in C/C++? A whole array cannot be passed as an argument to a function in C++. You can, however, pass a pointer to an array without an index by specifying the array's name. In C, when we pass an array to a function say fun(), it is always treated as a pointer by fun().

How do you pass a copy of an array to a function in C?

Answer: An array can be passed to a function by value by declaring in the called function the array name with square brackets ( [ and ] ) attached to the end. When calling the function, simply pass the address of the array (that is, the array's name) to the called function.


2 Answers

In funciton parameters, [] (without a dimension inside) is just alternate syntax for a pointer, as arrays decay to pointers when passed into functions, unless they're passed by reference.

This means that your working generalised template (the one with T a[]), is exactly the same as T a*. If you're passing the size in at runtime anyway, all is fine and you can just use that (and it will work for other things not declared as arrays, such as the return value of std::string::c_str()).

However, if you want to generalise the tempalte but still keep it limited to actual arrays, you can do this:

template<class T, size_t N>
T sum_array(T (&a)[N], int size)
{
    T result=0;
    for(int i=0; i<size; i++)
    {
        result = a[i] + result;
    }
    return result;
}

That way, only a genuine array can be passed in, but both its type T and its length N will be deduced. Depending on your use case, you might get away with removing the size parameter in such case.

like image 192
Angew is no longer proud of SO Avatar answered Oct 24 '22 20:10

Angew is no longer proud of SO


If you want to bind an array by reference, you will absolutely need to know the array's size. You can have the compiler deduce the size, however. Assuming the logic in your code is non-trivial, it is a good idea to immediately delegate to version which is independent of the array's size. Here is an example:

template<typename T>
T sum_array(T const* a, int size)
{
    return std::accumulate(a, a + size, T());
}

template <typename T, int Size>
T sum_array(T const (&array)[Size]) {
    return sum_array(array, Size);
}

Of course, I couldn't resist to also use std::accumulate() from <numeric>: if there is an algorithm for this, it is a good idea to use it.

Since you wondered about removing the reference from the array: when using T[] for the type of a function parameter, it is equivalent to using T*. Even if you'd use T[10] for the type of a function parameter, the compiler would read it as T*.

like image 28
Dietmar Kühl Avatar answered Oct 24 '22 19:10

Dietmar Kühl