2012-04-23 4 views
3

私は積分型(short、int、long)と浮動小数点型(float、double)の両方をとるMatrixクラスに取り組んでいます。 いくつかのメソッドを浮動小数点型(inversionメソッドなど)に限定し、いくつかのメソッドを浮動型および整数型(==演算子など)に対して異なる実装にする必要があります。 ブーストの「enable_if」と「is_integral」/「is_floating_point」を使用するのが正しい方法ですが、動作させることができません。タイプが整数型か浮動小数点型かに基づいてテンプレートメソッドを変更するにはどうすればよいですか?

error: no type named ‘type’ in ‘struct boost::enable_if<boost::is_integral<float>, float>’ 

と:私はこれらが最も関連性の高いものだと思う一方で、これはコンパイルエラーの多くを生産する

template <typename T> 
class Matrix 
{ 
    ... 
    bool operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const; 
    bool operator==(Matrix<typename enable_if<is_floating_point<T>::type T> >) const; 
    typename enable_if<is_floating_point<T> T> computeInverse() const; 
    ... 
}; 
// implementation 
bool Matrix<T>::operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const { 
    //implementation without precision 
} 
bool Matrix<T>::operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const { 
    //implementation using precision 
} 
Matrix<typename enable_if<is_floating_point<T> T>::type > Matrix<T>::computeInverse() const { 
    //implementation requiring floating points 
} 

私の実装では、このCに似た何か++半疑似コードであります

error: no type named ‘type’ in ‘struct boost::enable_if<boost::is_floating_point<int>, int>’ 

これは、異なる実装少なくともブーストのenable_ifを使用しないで、これは正しいですか?

もしそうなら、どうすればよいですか?私は、テンプレートの専門化が行く方法だと知っていますが、あまりにも多くのコードを複製しないようにしたいと思います。

+3

1つのテンプレートに実装を混在させるのではなく、2つの異なるタイプのマトリックスクラス全体を2つの特殊化し、共通部分にベースを分割することができますか? –

答えて

2

最も簡単なのはMatrixでオーバーロードされた関数を使用することです:

template <typename T> 
class Matrix 
{ 
    template <bool isInteger> class Discrim; 
    // ... 
    bool isEqual(Matrix const& other, Discrim<true>) const 
    { 
     // Integer implementation... 
    } 

    bool isEqual(Matrix const& other, Discrim<false>) const 
    { 
     // Floating point implementation... 
    } 

public: 
    bool isEqual(Matrix const& other) const 
    { 
     return isEqual(other, Discrim<std::numeric_limits<T>::is_integer>()); 
    } 
}; 

あなたoperator==operator!=が もちろん、Matrix::isEqualを呼び出します。

あなたのコメントから判断すると、 の機能は、Tが浮動小数点型であれば、あなたのコメントから判断してください。これをしないでください。 は人を混乱させるだけであり、道路の下で問題が終わることはありません(== は推移的な操作ではなくなります)。

+0

「ほぼ同等の」機能に関するお返事と頭をアップしてくれてありがとう。私は現在の問題の解決策を見つけたときに、これに対して別の解決策を検討します。 – jpihl

1

@DavidRodriguez's adviceに従ってください。クラスの共通機能を基本クラスに分ける必要があります。機能が異なる場合は、派生クラス全体の特殊化を提供します。それがより良いアプローチになります。あなたの現在の実装を維持したいならば、次のように

は、あなたがオーバーロードの解決のうち、オペレータの望ましくないバージョンをSFINAEことができます。

#include <iostream> 
#include <type_traits> 

template<class T> 
struct Matrix 
{ 
    // ... 
}; 

template<class T> 
typename std::enable_if< 
    std::is_integral<T>::value, bool 
    >::type 
operator==(const Matrix<T>&, const Matrix<T>&) 
{ 
    std::cout << "Integer version" << std::endl; 
    return true; 
} 

template<class T> 
typename std::enable_if< 
    !std::is_integral<T>::value, bool 
    >::type 
operator==(const Matrix<T>&, const Matrix<T>&) 
{ 
    std::cout << "Floating point version" << std::endl; 
    return true; 
} 

int main() 
{ 
    Matrix<int> m1, m2; 
    Matrix<double> m3, m4; 

    if(m1 == m2) {} 

    if(m3 == m4) {} 
} 

あなたは、私が知っている唯一の方法をメンバ関数としての演算子が必要な場合ダミーテンプレートパラメータを演算子に追加し、std::enable_ifテスト条件に&& std::is_same<T,U>を追加することです。