7

私は現在、次のシグネチャを持つ汎用ベクトルテンプレートクラス(コンテナではなく幾何学的エンティティ)を作成しています...


template< typename T, unsigned N >
class vector
{...}

...ここで、Tは算術型、Nは次元です。クロス積を演算子^(クラス定義内にある)のオーバーロードとして定義し、N==3の場合にのみ有効にします。


typename boost::lazy_enable_if_c< (N == 3), vector >::type
inline operator ^(const vector &rhs) const
{
    vector ret;
    ret(0) = val_[1] * rhs(2) - val_[2] * rhs(1);
    ret(1) = val_[2] * rhs(0) - val_[0] * rhs(2);
    ret(2) = val_[0] * rhs(1) - val_[1] * rhs(0);
    return ret;
}

残念ながら、このテンプレートをN!= 3でインスタンス化すると、演算子^が参照されていなくても、次のエラーが発生します。


error: no type named ‘type’ in ‘struct boost::lazy_enable_if_c < false, flare::math::vector < flare::math::fixed < short int, 8u >, 2u > >’

私は何が間違っているのですか?そのような場合、boost :: enable_ifに代わるものはありますか?

どうもありがとうございます。

4

2 に答える 2

5

エラーメッセージの主な原因は、ドキュメントによると、「の2番目の引数は、最初のパラメータ(条件)がtrueの場合は常にlazy_enable_if名前が付けられたネストされた型を定義するクラス型である必要があります」です。typeこれは明らかにここでは満足できません(vectorタイプにが含まれている場合を除きますtypedef something type;)。

ここは必要ありませんlazy_...。ドキュメントによると、これは2番目の引数が未定義である可能性がある場合にのみ必要です(たとえば、2番目の引数がtypename foo<T>::barであり、barタイプがすべてのタイプに対して定義されていない場合T)。 vector(ここではvector<T, N>)が常に定義されます。

したがって、必ず、を削除lazy_するか、何もしない特性クラスtemplate <typename T> struct nop { typedef T type; };を作成して、2番目の引数をに置き換えてみlazy_enable_if_cnop<vector>ください。しかし、私の推測では、少なくとも前者はすでに試しています。:)

そして今、私はそれがうまくいかない理由がわかります。 標準14.7.1/1によると:

クラステンプレートの特殊化が明示的にインスタンス化されている(14.7.2)または明示的に特殊化されていない(14.7.3)場合を除き、完全に定義されたオブジェクトタイプを必要とするコンテキストで特殊化が参照される場合、または完全性がある場合、クラステンプレートの特殊化は暗黙的にインスタンス化されます。クラスタイプのは、プログラムのセマンティクスに影響します。クラステンプレート特殊化の暗黙的なインスタンス化により、クラスメンバー関数、メンバークラス、静的データメンバー、およびメンバーテンプレートの宣言の暗黙的なインスタンス化が発生しますが、定義やデフォルトの引数のインスタンス化は発生しません。

したがって、クラスがインスタンス化される原因となるものはすべて、すべてのメソッドの宣言をインスタンス化しようとしますが、。の場合は失敗しN != 3ます。したがって、代わりに関数テンプレートに渡す常に存在するメソッドを使用する必要があるようです。心配しないでください。まともなコンパイラは、これを介してインライン化できます。

template< typename T, unsigned N > class vector;   // Fwd decl.

template< typename T, unsigned N >
inline boost::enable_if_c< (N == 3), vector<T, N> >::type
magic(const vector<T, N>& lhs, const vector<T, N>& rhs) {
    /* Do the calculation as before... */
    return ret;
}

template< typename T, unsigned N >
class vector {
    ...
    inline vector operator ^(const vector &rhs) const {
        return magic(*this, rhs);
    }
};

これが機能するのは、メンバー関数の定義が実際に呼び出されない限り(またはアドレスが取得されない限り)インスタンス化されないためです。

于 2010-11-28T11:37:57.203 に答える
2

あなたの問題は「クラス定義の中にある」と思います。メソッドではなく関数を使って演算子をオーバーロードすれば、問題は少なくなると思います。

関数に切り替えたら、魔法をブーストするのではなく、昔ながらの専門分野だけでうまくいくこともできると思いますが、それについてはよくわかりません。

于 2010-11-28T06:30:08.093 に答える