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.
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.
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 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().
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.
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.
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*
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With