0

Eigen線形代数ライブラリ(リンク)のテンプレート化されたMatrixクラスを使用しています。Matrixクラスは、3つの名目上のテンプレートパラメーターを取ります。

Matrix<type, rows, cols>

上記では、の例は、、typeまたはdoubleですstd::complex<double>。また、rowsは行数、colsは行列の列数です。

以下のコードに示されているように、私がやりたいのは、条件付きステートメントを使用して、実行時に別のテンプレート化されたMatrixクラスを使用することです。

頭に浮かぶ最初の解決策は、voidポインタを使用することかもしれません。

#include <iostream>
#include <Eigen/Dense>
#include <complex>

using namespace Eigen;

int main()

{  
    // this flag is set at run-time, but it is only set here
    // in the code as an example
    int create_complex = 1;
    void *M;

        if(create_complex)
    {
        Matrix<std::complex<double>,3,3> m0;
        M = &m0;
    }
    else
    {
        Matrix<double,3,3> m0;
        M = &m0;
    }
    // de-reference pointer here and use it    

 return 0;
}

このコードはコンパイルされますが、void *M使用する前にポインターを明示的に参照解除する必要があります。同じプログラムロジックに対して異なるコードブロックを作成する必要があるため、これは不便です。

ここで適用される可能性のあるポリモーフィズムに似たものがあるのではないかと思います。ここでは、voidポインターを使用する必要はありません。

4

3 に答える 3

2

これは不便です

「不便」を「違法」と読んだ場合、あなたはその場にいます。

ローカル変数は、スコープが終了すると(つまり、終了時に})破棄されるため、ダングリングポインターが残ります。そのため、参照を解除しようとすると、未定義の動作に遭遇します。

Matrix<std::complex<double>,3,3>Matrix<double,3,3>は完全に無関係なクラスであるため、これを行う簡単な方法はありません。もう一度言います。それらは完全に無関係なクラスです。

別の方法はMatrix、基本タイプがあり、それへのポインターがあるが、動的割り当てが必要になることです。何かのようなもの:

BaseMatrix* m;
if ()
    m = new Matrix<std::complex<double>,3,3>;
else 
    m = new Matrix<double,3,3>;
于 2012-12-06T21:22:40.423 に答える
2

行列タイプに基づいて独自の関数をテンプレートとして記述し、条件文でその異なるバージョンを呼び出すことができます。

テンプレートはコンパイル時にコードを生成するためのものであるため、これが唯一の方法です。コンパイル時にすべてのコードパスを生成してから、そのうちの1つを選択する必要があります。

于 2012-12-06T21:24:28.927 に答える
1

メソッドもテンプレート化する必要があります。

template<class T>
my_main() { 

   Matrix<T,3,3> m0;

   // ...


}

アップデート

または、クラスを定義できます

#ifndef CREATE_COMPLEX
    typedef double MyClass;
#else
    typedef std::complex<double> MyClass;
#endif

main() { 

   Matrix<MyClass,3,3> m0;

   // ...


}

これらの定義をプリプロセッサ定義と切り替えることができます。

于 2012-12-06T21:26:22.413 に答える