2010-08-19 42 views
2

基本上,我有一個矩陣類像這樣(有很多運算符重載等功能去掉):模板化矩陣類不產生正常運行

template 
< 
    uint32 TRows, 
    uint32 TCols 
> 
struct Matrix 
{ 
    float values[TRows][TCols]; 

    inline explicit Matrix() 
    { 
    } 

    inline Matrix<TRows - 1, TCols - 1> minor(const uint32 col, const uint32 row) 
    { 
     Matrix<TRows - 1, TCols - 1> matrix; 
     for(int i = 0; i < TRows; ++i) 
      for(int j = 0; j < TCols; ++j) 
      { 
       if(i == col || j == row) continue; 
       matrix.values[i - (i > col)][j - (j > row)] = this->values[i][j]; 
      } 
     return matrix; 
    } 

    inline float determinant() 
    { 
     if(TRows != TCols) throw DimensionError("Matrix is not square"); 

     float det = 0; 

     if(TRows <= 0) 
      det = 0; 
     else if(TRows == 1) 
      det = this->values[0][0]; 
     else if(TRows == 2) 
      det = this->values[0][0] * this->values[1][1] - this->values[1][0] * this->values[0][1]; 
     else 
      for(int j = 0; j < TCols; ++j) 
       det += (j % 2 ? -1 : 1) * this->values[0][j] * this->minor(0, j).determinant(); 

     return det; 
    } 
} 

我不明白爲什麼,對於線det += (j % 2 ? -1 : 1) * this->values[0][j] * this->minor(0, j).determinant(); ,GCC嘗試生成功能的巨大數額:

matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -49u, unsigned int TCols = -49u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -48u, unsigned int TCols = -48u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -47u, unsigned int TCols = -47u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -46u, unsigned int TCols = -46u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -45u, unsigned int TCols = -45u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -44u, unsigned int TCols = -44u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -43u, unsigned int TCols = -43u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -42u, unsigned int TCols = -42u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -41u, unsigned int TCols = -41u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -40u, unsigned int TCols = -40u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -39u, unsigned int TCols = -39u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -38u, unsigned int TCols = -38u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -37u, unsigned int TCols = -37u]' 
matrix.cpp:95: instantiated from `float Matrix<TRows, TCols>::determinant() [with unsigned int TRows = -36u, unsigned int TCols = -36u]' 

這可能是我的代碼一定的誤差,但我不能爲我的生命看到我要去哪裏錯了。幫助將非常感謝!

回答

4

Matrix :: minor(0,j)返回大小爲(N-1,N-1)的矩陣。 調用它的行列式使得這個過程是遞歸的,這意味着你爲所有p個整數生成一個次要的(和行列式方法),從N開始到... -infinity?

您是否在N == 1或N == 0的情況下添加了專門化? 你必須確保遞歸停止!

嘗試添加類似:

template<> 
struct Matrix<1,1> 
{ 
    float values[1][1]; 

    float determinant(){ return values[0][0]; } 
}; 

編輯: 遞歸必須在編譯時停止。在該方法內部添加if語句並不妨礙編譯器編譯所有可能的路徑。

+0

謝謝!有用!只是在你的代碼中的一個小錯字 - 'int float'應該簡單地'float':) – rfw 2010-08-19 09:32:21

+0

@rfw:這是一個動態時間分支,你需要一個靜態時間分支。爲0大小的矩陣添加專門化。 – GManNickG 2010-08-19 09:37:15

0

我同意「伯努瓦」

偶數事實運行你從來沒有呼籲「空」矩陣minor功能時 - 不阻止編譯器生成的代碼。

要避免這種情況,您應該玩顯式模板專業化。所以即使在編譯時編譯器也不會遇到導致無限模板函數生成的程序路徑。

像這樣的:這種類型的專業化的

template <int N> 
float determinantInternal() 
{ 
    // Standard algoritm for NxN matrix 
    float det = 0; 
    for(int j = 0; j < TCols; ++j) 
     det += (j % 2 ? -1 : 1) * this->values[0][j] * this->minor(0, j).determinant(); 

    return det; 
} 

template <> 
float determinantInternal<0>() 
{ 
    return 0; 
} 

float determinantInternal<1>() 
{ 
    return this->values[0][0]; 
} 

float determinantInternal<2>() 
{ 
    return this->values[0][0] * this->values[1][1] - this->values[1][0] * this->values[0][1]; 
} 

template <> 
float determinant() 
{ 
    if (TRows != TCols) 
     throw DimensionError("Matrix is not square"); 
    // Alternatively you can use something to prevent this from compiling. 
    // This way you produce the compile-time error if attempted to call 
    // determinant on a non-square matrix 
    BOOST_STATIC_ASSERT(TRows == TCols); 

    return determinantInternal<TRows>(); 
} 

還有一個好處是,你在處理不同類型的基質(空,非正方形,1x1的,爲N×N)編譯時間。因此你會得到更快的代碼。

另外,您可以防止在非方形矩陣上調用determinant。在這種情況下,嘗試執行時會遇到編譯器/鏈接器錯誤,而不是運行時的異常。