2011-06-05 18 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; 
    }; 

私はTransposeテンプレートをMyMatrix(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 A:これを汎用のマトリックスライブラリとして使用するつもりはないが、私は特定の(事前に知られている)サイズの行列を操作したいと思っています。アプローチ。行列のメモリレイアウトを最適化することができます(たとえば、32バイトの境界で行ベクトルを整列させるなど)。そして、他の種類のファンキーなものを実行できます。私はこれを行うことで足の中で自分自身を大変な時間をかけて撃つことを期待していますが、私がここに到達しようとしている主なことは、何がうまくいくのか、何ができないのかを見つけることです't)。

@Bo Perrson:私は最初のバージョンがコンパイルされない理由を知っていますが、私の2回目の試行がより簡単なバージョンであればうれしいです。主な問題は、MyMatrixはクラステンプレート自体であり、Transpose-structにテンプレート引数を何とか取得する必要があることです。

@VJo:うまくいくとは思わない。 TがMyMatrix < ..>そのものなら、転置行列はT自体ではなく、データ型としてTranspose<T>になるはずです。すべての基本型(char、int、double ...)に対して、これはもちろん正しい方法です。

答えて

0

テンプレート定義のrows/colsを作ることから得られるものは何ですか?

私の個人的な感想は、これは物事が複雑すぎるということです。テンプレートにはデータタイプが含まれていますが、寸法を含めて間違っているようです。

+2

おそらく、コンパイラが小さな行列に対して操作をオープンすることができますコンパイル時定数彼は正しいかもしれない。 – Nemo

+0

@Nemo - ああ、OK - C++は私のものではありません - それは私には奇妙に思えました。ありがとうございました。 –

+1

フィールドによっては、追加の型の安全性も役立ちます。また、基礎となるデータ構造のヒープ以外の割り当ても可能です。最終的には、より一般的な解決法が通常はより良い呼び出しですが、ユニークなタイプの方が有利です。 –

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

専門はセパレート型のテンプレートパラメータであるため、最初の試みは失敗しました基本テンプレートはそこではわかりません。

言語に応じて2番目の判断は正しいですが、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を無料で入手することができます。

関連する問題