2013-06-02 68 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 /容器/陣列)。 –