1

実装する必要のあるアルゴリズムに合わせて非常に調整された行列クラスがあります。私はエイゲンについて知っていますが、それは私の法案に合わないので、私は自分でやらなければなりませんでした。私は列メジャーの順序付けに取り組んできましたが、行メジャーを使用する強力なユースケースもあるので、順序付けを定義する追加のテンプレートパラメーターを使用してテンプレートマトリックスクラスを特殊化したいのですが、したくありません。既存のコードを壊します。

これの具体的な効果は、テンプレートの部分特殊化を使用して、2つまたは3つの主要なクラスメソッドを異なる方法で生成することです。たとえばoperator(int i, int j)、異なる順序を定義します。プリプロセッサを使用して同様の概念を実行できます#defineが、これはあまりエレガントではなく、すべてをコンパイルするだけで機能します。いずれかのモードで。これは私が達成しようとしていることのスケッチです:

enum tmatrix_order {
    COLUMN_MAJOR, ROW_MAJOR
};

/**
* Concrete definition of matrix in major column ordering that delegates most
* operations to LAPACK and BLAS functions. This implementation provides support
* for QR decomposition and fast updates. The following sequence of QR updates
* are supported:
*
* 1) [addcol -> addcol] integrates nicely with the LAPACK compact form.
* 2) [addcol -> delcol] delcols holds additional Q, and most to date R
* 3) [delcol -> delcol] delcols holds additional Q, and most to date R
* 4) [delcol -> addcol] delcols Q must also be applied to the new column
* 5) [addcol -> addrow] addrows holds additional Q, R is updated in original QR
* 6) [delcol -> addrow] addrows holds additional Q, R is updated in original QR
*/
template<typename T, tmatrix_order O = COLUMN_MAJOR>
class tmatrix {
private:
    // basic matrix structure
    T* __restrict m_data;
    int           m_rows, m_cols;     
// ...
};

template <typename T>
inline T& tmatrix<T, COLUMN_MAJOR>::operator()(int i, int j) {
  return m_data[j*m_rows + i];
}

template <typename T>
inline const T& tmatrix<T, COLUMN_MAJOR>::operator()(int i, int j) const {
  return m_data[j*m_rows + i];
}

template <typename T>
inline T& tmatrix<T, ROW_MAJOR>::operator()(int i, int j) {
  return m_data[i*m_cols + j];
}

template <typename T>
inline const T& tmatrix<T, ROW_MAJOR>::operator()(int i, int j) const {
  return m_data[i*m_cols + j];
}

しかし、コンパイラは部分的な特殊化について文句を言います。

/Users/bravegag/code/fastcode_project/code/src/matrix.h:227:59: error: invalid use of incomplete type 'class tmatrix<T, (tmatrix_order)0u>'
/Users/bravegag/code/fastcode_project/code/src/matrix.h:45:7: error: declaration of 'class tmatrix<T, (tmatrix_order)0u>'

ただし、以下に示すようにこれらの機能を完全に専門化すると機能しますが、これは非常に柔軟性がありません。

inline double& tmatrix<double, COLUMN_MAJOR>::elem(int i, int j) {
  return m_data[j*m_rows + i];
}

これは言語の部分的なテンプレートの特殊化のサポートの問題ですか、それとも間違った構文を使用していますか?

4

2 に答える 2

3

考えられる解決策:

enum tmatrix_order {
  COLUMN_MAJOR, ROW_MAJOR
};

template<typename T>
class tmatrix_base {
  protected:
    // basic matrix structure
    T* __restrict m_data;
    int           m_rows, m_cols;
};     

template<typename T, tmatrix_order O = COLUMN_MAJOR>
class tmatrix : public tmatrix_base<T>{
  public:
    tmatrix() {this->m_data = new T[5];}
    T& operator()(int i, int j) {
      return this->m_data[j*this->m_rows + i];
    }
    const T& operator()(int i, int j) const {
      return this->m_data[j*this->m_rows + i];
    }
};

template<typename T>
class tmatrix<T, ROW_MAJOR> : public tmatrix_base<T>{
  public:
    tmatrix() {this->m_data = new T[5];}
    T& operator()(int i, int j) {
      return this->m_data[i*this->m_cols + j];
    }
    const T& operator()(int i, int j) const {
      return this->m_data[i*this->m_cols + j];
    }
};

int main()
{
  tmatrix<double, COLUMN_MAJOR> m1;
  m1(0, 0);
  tmatrix<double, ROW_MAJOR> m2;
  m2(0, 0);
}

特殊なクラスの関数だけを提供するのではなく、完全なクラス定義を提供するという考え方です。基本的な問題は、コンパイラがそのクラスの定義が他に何であるかを知らないことだと思います。

:テンプレート化されたベースメンバーにアクセスできるようにする必要がありますthis->。そうしないと、ルックアップが失敗します。

:コンストラクターはそこにあるので、爆破せずにmain関数をテストできます。あなたはあなた自身のものを必要とするでしょう(私はあなたがすでに持っていると確信しています)

于 2012-06-08T13:51:56.590 に答える
2

シンプルに保ち、次のように記述します。

template <typename T, tmatrix_order O>
inline T& tmatrix<T, O>::operator()(int i, int j) {
  if (O == COLUMN_MAJOR) {
    return m_data[j*m_rows + i];
  } else {
    return m_data[i*m_cols + j];
  }
}

言語仕様によって保証されているわけではありませんが、コンパイラはコンパイル時定数との比較を最適化すると思います。

于 2012-06-08T14:06:52.157 に答える