Reputation: 200
i have to make a metaprograming template where I have to detect a size of array. So the the template wich detect size of array:
template<typename T, size_t N>
size_t arraylen( T(&)[N] )
{ return N; }
This works fine, but dosent works with this template
//Template to calculate Vector*Vector
template<int N> double IloczynSkalarny(double *a,double *b) {
return (*a)*(*b)+IloczynSkalarny<N-1>(++a,++b);
}
template<> double IloczynSkalarny<1>(double *a,double *b) {
return (*a)*(*b);
}
//Here we calculate the row of matrix using Vector*Vector template
template<int M,size_t I> double row_vec(double *A,double *v) {
return IloczynSkalarny<M>(A+I*M,v);
}
//Looping thru matrix rows
template<int N,int M> struct matrix_vec_c {
static void matrix_vec(double *A,double *v,double *u) {
u[N-1]=row_vec<M,N-1>(A,v);
matrix_vec_c<N-1,M>::matrix_vec(A,v,u);
}
};
template<int M> struct matrix_vec_c<0,M> {
static void matrix_vec(double *A,double *v,double *u) {}
};
//Calling template
template<size_t N,size_t M> inline void matrix_vec(double A[],double v[],double u[]) {
matrix_vec_c<N,M>::matrix_vec(A,v,u);
}
This template works well when i give the parameters N i M like this
double x[] = {1, 1, 0};
double A[] = {1, 0, 0,
2, -5, 1};
double y[2];
matrix_vec<2,3>(A,x,y);
But i need to call matrix_vec like this:
matrix_vec(A,x,y);
Where no N i M parameters pass to template. So I have to detect the size of arrays. So I make template like this:
inline void matrix_vec(double A[],double v[],double u[]) {
int N = arraylen(v);
int M = arraylen(u);
matrix_vec_c<N,M>::matrix_vec(A,v,u);
}
But i get error: no matching function for call to 'arraylen(double*&)'
When I put const values of N i M its works:
inline void matrix_vec(double A[],double v[],double u[]) {
int const N = 3;
int const M = 3;
matrix_vec_c<N,M>::matrix_vec(A,v,u);
}
Of course that have no sense because the passed arrays have various sizes. The template function arraylen works fine but in my template dosent what I make wrong?
PS Arrays are in C style no C++ like std::vector or others
Upvotes: 1
Views: 253
Reputation: 490098
That's at least a large part of the point of using this template in the first place -- it'll only work when it's passed an actual array. When you try to use it inside the function, the function parameter has already decayed from array to pointer. Since you can't invoke the template on a pointer, compilation fails.
To make things work you could (for one example) make the function into a template that also receives a reference to an array. This would preserve the "array" nature of the argument into the function itself (just like it does in your template).
template <class T, size_t N>
size_t sum(T(&matrix)[N]) {
// use matrix. For this example, we'll sum its elements:
size_t total = 0;
for (size_t i=0; i<N; i++)
total += matrix[i];
return total;
}
Which you could use something like this:
int main() {
int x[] = {1, 3, 5, 7, 9};
std::cout << sum(x);
return 0;
}
Note, however, that in this case you don't really need your arraylen
, because the size of the array (N) is available directly.
The other way to make it work (the better way, IMO) is to just say no to arrays. Pass a std::vector
, for example, and the whole problem just disappears completely -- you don't need a special template hack to get the length in the first place, you just call your_vector.size()
and it's all good.
Upvotes: 3
Reputation: 409166
It's because when you pass arrays to a function, they are no longer arrays but has decayed to pointers. Arrays and pointers are pretty much interchangeable, but with the difference that a pointer of course doesn't have a size.
Upvotes: 2