I know how to write a variadic template function that accepts a variable number of arguments:
template<int I, typename... Rest>
void f() {
// whatever
}
and I know how to write a template function that accepts a reference to an array:
template<typename T, unsigned int Length>
void f(T(&arr)[Length]) {
// whatever
}
but I cannot think of how to combine the two so that the function accepts a variable number of references to arrays.
My first attempt was
template<typename T, unsigned int Length>
unsigned int arrlen(T(&)[Length]) {
return Length;
}
template<typename T, unsigned int Length>
int f(T(&arr)[Length]) {
return Length;
}
template<typename T, unsigned int Length, typename... Rest>
int f(T(&arr)[Length], Rest... rest) {
return Length + f(rest...);
}
int main() {
int a[] = {1 , 2, 3}, b[] = {1, 2, 3, 4, 5}, c[] = {1};
cout << f(a, b, c);
}
But the compiler tells me
a.cpp: In function 'int f(T (&)[Length], Rest ...) [with T = int, unsigned int Length = 3u, Rest = {int*, int*}]'
a.cpp:23:22: instantiated from here
a.cpp:17:27: error: no matching function for call to 'f(int*&, int*&)'
a.cpp:17:27: note: candidates are:
a.cpp:11:22: note: template int f(T(&)[Length])
a.cpp:16:5: note: template int f(T(&)[Length], Rest ...)
So I was thinking that you could write an object that would store the length of the array it was constructed with, and then pass a variable number of those (which would be implicitly constructed from the arrays passed) to the function. Here is my try at that:
template<typename T, unsigned int Length>
struct Array {
Array(T(&arr)[Length]) : arr(arr), len(Length) { }
T(&arr)[Length];
const unsigned int len;
};
int f() {
return 0;
}
template<typename T, unsigned int Length, typename... Args>
int f(const Array<T, Length>& a1, Args... rest) {
return a1.len + f(rest...);
}
int main() {
int a[] = { 1, 2, 3 }, b[] = { 1, 2, 3, 4, 5 }, c[] = { 1 };
cout << f(a, b, c);
}
But when I try to compile it with GCC 4.6.1 I get the error
a.cpp: In function 'int main()':
a.cpp:27:22: error: no matching function for call to 'f(int [3], int [5], int [1])'
a.cpp:27:22: note: candidates are:
a.cpp:16:47: note: template int f(const Array&, Args ...)
a.cpp:20:5: note: int f()
a.cpp:20:5: note: candidate expects 0 arguments, 3 provided
However, besides fixing the second code (which is more of a workaround for not knowing how to do what I really want to do), the actual point of this question and the thing I would actually like to learn is how to do this without using proxy objects like that if possible, like the first code. So how can this be done? Was there just a simple syntax error in one of the tries I posted?
std::array
and forget about raw array nonsense. – Cat Plus Plusstd::array
doesn't decay to pointer, so you don't have to play with size passed as a template argument. – Cat Plus Plus