C ++元编程检测大小数组

时间:2013-06-02 15:24:29

标签: c++ arrays size detect template-meta-programming

我必须制作一个元编程模板,我必须检测数组的大小。 所以模板检测到数组的大小:

template<typename T, size_t N>
size_t arraylen( T(&)[N] )
{ return N; }

这样可以正常使用,但剂量适用于此模板

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

当我给出像这样的参数N i M时,这个模板效果很好

double x[] = {1, 1, 0};
double A[] = {1, 0, 0,

              2, -5, 1};
double y[2];
matrix_vec<2,3>(A,x,y);

但我需要像这样调用matrix_vec:

matrix_vec(A,x,y);

没有N i M参数传递给模板。所以我必须检测数组的大小。 所以我制作这样的模板:

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

但我得到错误:没有匹配函数来调用'arraylen(double *&amp;)'

当我把N i M的const值设为其工作时:

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

当然没有任何意义,因为传递的数组有各种大小。 模板函数arraylen工作正常,但在我的模板中,我做错了什么?

PS 数组采用C风格,没有C ++,如std :: vector或其他

2 个答案:

答案 0 :(得分:3)

这至少是使用此模板的重要部分 - 它只会在传递实际数组时才有效。当您尝试在函数内部使用它时,函数参数已经从数组衰减到指针。由于无法在指针上调用模板,因此编译失败。

为了使工作正常,您可以(例如)将函数转换为模板,该模板也接收对数组的引用。这会将参数的“数组”性质保留在函数本身中(就像在模板中一样)。

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

您可以使用以下内容:

int main() { 
    int x[] = {1, 3, 5, 7, 9};
    std::cout << sum(x);
    return 0;
}

但请注意,在这种情况下,您并不真正需要arraylen,因为数组的大小(N)可以直接使用。

使其工作的另一种方式(更好的方式,IMO)就是对数组说不。例如,传递一个std::vector,整个问题就完全消失了 - 你不需要一个特殊的模板黑客来获取长度,你只需要调用your_vector.size()就可以了

答案 1 :(得分:2)

这是因为当你将数组传递给一个函数时,它们不再是数组,而是已经衰减为指针。数组和指针几乎可以互换,但不同之处在于指针当然没有大小。