2011-06-05 149 views
3

我想通過創建一個包含矩陣和這些矩陣上的操作的庫來塑造我的模板技能(我知道的很少)。基本上,我想我的矩陣是非常強類型的(數據類型和大小在編譯時已知),我也希望能夠自動扣除轉置矩陣的類型。專門用模板類作爲參數的模板結構

template< typename TDataType, size_t rows, size_t cols > class MyMatrix

矩陣可以嵌套,所以TDataType可以是整體式的,但也有MyMatrix<...>本身,導致數據類型的轉置矩陣是不必相同的原始矩陣中的一個,例如: Transpose(MyMatrix< MyMatrix< char, 2, 3 >, 4, 6 >) ==> MyMatrix< MyMatrix< char, 3, 2 >, 6, 4 >(外基質的數據類型已改變)

我給轉置型扣第一嘗試是:

template< typename TDataType > 
struct Transpose 
    { 
    typedef TDataType type; 
    }; 

template<> 
struct Transpose< MyMatrix<TDataType, rows, cols> > 
    { 
    typedef MyMatrix<typename Transpose<TDataType>::type, cols, rows> type; 
    }; 

我找不到這樣做的原因,因爲我似乎無法使用MyMatrix專門化Transpose-template(TDataType未知和類似的錯誤)。

唯一的解決辦法編譯我想出了(我甚至不知道是否可行尚)是這樣的:

template< typename TMatrixType, typename TDataType, size_t rows, size_t cols > 
struct Transpose 
    { 
    typedef TMatrixType type; 
    }; 

template< typename TDataType, size_t rows, size_t cols > 
struct Transpose< MyMatrix<TDataType, rows, cols>, TDataType, rows, cols > 
    { 
    typedef MyMatrix< typename Transpose<TDataType,TDataType,rows,cols>::type, cols, rows > type; 
    }; 

我相信我做的事情太複雜;有沒有更容易的解決方案來實現我想要的?


一個問題的答案,我的問題(我張貼的問題,沒有一個帳戶,所以我沒有足夠的代表處做的事情正常的方式)。非常感謝!

@Bo Persson @Will答:我不打算把它用作通用矩陣庫,我想在特定的(已知的)大小的矩陣上執行操作,並想通過使用這個做法。它可以讓我優化矩陣的內存佈局(例如,在32字節的邊界上對齊行向量)並做其他各種時髦的事情。我希望通過這樣做讓自己在腳下受到很多時間的傷害,但是我想要獲得的主要內容是經驗,並找出哪些是有效的,什麼不是(以及什麼是難以做到的,什麼是不可行的「T)。

@Bo Perrson:我知道爲什麼第一個版本不能編譯,但我想知道是否有我的第二次嘗試可以工作的簡單版本。主要問題是MyMatrix本身就是一個類模板,我需要將它的模板參數以某種方式傳遞給Transpose-struct。

@VJo:我不認爲那會奏效。如果T是MyMatrix < ..>,則轉置矩陣應該有Transpose<T>作爲數據類型,而不是T本身。對於所有基本類型(char,int,double ...),這當然是正確的並且更簡單。

回答

0

從模板定義的行/列部分獲得什麼?

我個人的感覺是這樣做太複雜了。儘量在模板中包含數據類型,但包括尺寸似乎是錯誤的。

+2

他可能認爲編譯器可以在小矩陣上打開編碼操作(從而避免循環開銷),當邊界是編譯時常量。他可能是對的。 – Nemo 2011-06-05 17:52:53

+0

@Nemo - 啊,OK - C++不是我的東西(再多) - 所以對我來說似乎很奇怪。感謝尼莫。 – 2011-06-05 17:53:47

+1

根據您的字段,附加類型安全性也可能有用,它還允許您的基礎數據結構的非堆分配。最終,更一般的解決方案通常是更好的召喚,但肯定有贊成獨特類型的論點。 – 2011-06-05 18:23:37

3

是的,你很複雜。

如果有聲明是這樣的:

template< typename TDataType, size_t rows, size_t cols > class MyMatrix 

然後轉置函數應該是這樣的:

template< typename T, size_t rows, size_t cols > 
MyMatrix< T, cols, rows > Transpose(const MyMatrix< T, rows, cols > & m) 
{ 
    MyMatrix< T, cols, rows > res; 
    // implementation 
    return res; 
} 
0

因爲專業化是一個單獨的類型和模板參數的第一次嘗試失敗基本模板在那裏是不知道的。

根據語言,第二個verision是正確的,但是就像Will A說的那樣 - 你是否真的希望每一個行和列的組合都創建一個新類型?

0

我會寫這樣的事情,允許遞歸的任意深度(矩陣的矩陣的矩陣...)

template<typename T, unsigned rows, unsigned cols> 
struct MyMatrix 
{ 
    typedef T value_type; 
    T stuff[rows][cols]; // or whatever          
}; 

// For basic types, transpose is identity.         
template<typename T> 
struct Transpose { 
    typedef T result_type; 
    result_type operator()(const T & in) { 
    return in; 
    } 
}; 

// For more complex types, specialize and invoke recursively. 
template<typename T, unsigned rows, unsigned cols> 
struct Transpose<MyMatrix<T, rows, cols> > { 
    typedef MyMatrix<Transpose<T>, cols, rows> result_type; 
    result_type operator()(const MyMatrix<T, rows, cols> & in) { 
    Transpose<T> transposer; 
    // (invoke transposer on each element of in and build result)   
    } 
}; 

這裏,移調是一個仿函數;您創建它的一個實例,但將其稱爲函數。對於額外的功勞,你可以讓它繼承unary_function並免費獲得result_type typedef ...