2013-06-02 32 views
0

我必须做一个元编程模板,我必须检测数组的大小。 数组所以模板至极检测尺寸:C++元编程检测大小数组

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

这工作得很好,但dosent作品与此模板

//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个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(双* &)'

当我把N个常量值I M没有匹配功能的作品:

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正常工作,但在我的模板dosent我做错了什么?

PS 数组在C中的风格没有类似于C++的std ::向量或其他

+0

'return(* a)*(* b)+ IloczynSkalarny (++ a,++ b);'这是未定义的行为。 – jrok

+0

但这个模板工作正常我没有这个模板的问题。 – Aku

+0

未定义的行为并不意味着它不会编译。相反,它可能不会做你期望它做的事,或者看起来随机的场合失败。 –

回答

2

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

为了使事情能够正常工作,您可以(例如)将该函数放入一个也接收对数组的引用的模板中。这会将参数的“数组”性质保存到函数本身中(就像它在模板中一样)。

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()即可,这一切都很好。

+0

我知道std :: vector和C++的东西是更好的方法,但这里的数组是C风格的。 – Aku

+0

此代码剂量编译错误:在''''令牌之前预期的非限定id。在行类matrix_vec(T(&矩阵)[N]){ – Aku

+0

@ Aku:糟糕 - 相当真实。我写的是某种模板类和模板函数的混淆,它们都不起作用。我相信我现在已经纠正过了。 –

2

这是因为当你通过阵列的功能,它们不再是阵列,但已经衰减到指针。数组和指针几乎可以互换,但区别在于指针当然没有大小。

+0

那么如何在这种情况下检测数组的大小呢? – Aku

+0

同意,尝试,测试,工作。 –

+0

@Aku你不能,不管怎样都不能使用普通的数组。我建议你看看['std :: vector'](http://en.cppreference.com/w/cpp/container/vector)或['std :: array'](http://en.cppreference的.com /瓦特/ CPP /容器/阵列)。 –