2017-03-27 2 views
0

私は、1つのタイプのインスタンスを別のタイプ(例:Matrix<int>Matrix<double>)に直観的にキャストしたいテンプレートマトリックスクラスを持っています。キャストテンプレート(マトリックス)クラス

次のようにクラスを含むヘッダファイルを検索します:

#ifndef MATRIX_H 
#define MATRIX_H 

#include <cstdlib> 
#include <vector> 

template <class T> class Matrix 
{ 

    private: 

    std::vector<T>  _data; 
    std::vector<size_t> _shape; 
    std::vector<size_t> _strides; 

    public: 

    Matrix    (const Matrix<T> &) = default; 
    Matrix<T>& operator= (const Matrix<T> &) = default; 

    Matrix<T>(){}; 

    // explicit constructor 
    Matrix<T>(size_t nrow , size_t ncol) 
    { 
     _shape.push_back(nrow); 
     _shape.push_back(ncol); 

     while (_data.size()<_shape[0]*_shape[1]) 
     _data.push_back((T)0); 
    }; 

    T& operator[] (size_t i) 
    { return _data[i]; }; 

    T& operator() (size_t i, size_t j) 
    { return _data[i*_shape[1]+j]; }; 

    size_t size (void) const 
    { return _data.size(); }; 

    std::vector<size_t> shape (void) const 
    { 
     std::vector<size_t> ret(2); 
     for (size_t i=0 ; i<2 ; i++) 
     ret[i] = _shape[i]; 
     return ret; 
    }; 

}; 

#endif 

私には、最も直感的な方法は、次の2つのオプション(オプションX以下NBラインがコンパイルされません)の一つであります私は(私はそれが些細な何かのためにあまりにもカスタムですので、程度の超好きではないです)、次のソリューションを使用瞬間

#include "matrix.h" 

int main (void) 
{ 
    Matrix<int> matInt({5,5}); 

    for (size_t i=0 ; i<matInt.size() ; i++) 
    matInt[i] = static_cast<int>(i); 

    // Option 1 
    Matrix<double> matDouble = matInt; 

    // Option 2 
    Matrix<double> matDouble = static_cast<Matrix<double>>(matInt); 

    return 0; 
} 

Matrix<double> as_double (void) { 
    Matrix<double> out(this->shape()); 

    for (size_t i=0 ; i<this->size() ; i++) 
    out[i] = static_cast<double>(_data[i]); 

    return out; 
} 

答えて

1

std::vector<T>std::vector<U>に割り当てられないため、メンバーを割り当てることはできませんが、明示的に変換を行う必要があります。

あなたが書くことができconversion operator

template<typename U, 
typename V = T, typename = typename std::enable_if<std::is_convertible<T, U>::value>::type> 
operator Matrix<U>() { 
    Matrix<U> mat(shape()[0], shape()[1]); 
    for (size_t i = 0 ; i < size() ; ++i) { 
     mat[i] = static_cast<T>(_data[i]); 
    } 
    return mat; 
} 

enable_if#include <type_traits>)を削除することができますが、それはすなわちMatrix<std::string> mat = Matrix<int>();

のサイレント通過を許可しないので、また、それはおそらく良いアイデアだ私のアドバイスは、それを維持します現在不要なアルゴリズムの複雑さがあるため、_data.resize(_shape[0] * _shape[1]);を使用してください。

1

"テンプレートコピーコンストラクタ"(並べ替え)を定義する必要があります。既存のコンストラクタをクリーンアップすることから始めましょう:

Matrix<T>(size_t nrow , size_t ncol) 

これは必須ではありません。テンプレート擬似コピーコンストラクタを定義し、次に

Matrix(size_t nrow , size_t ncol) 

template<typename From> 
Matrix(const Matrix<From> &s) 

、あなたはコピーコンストラクタを書いたかのように、このコンストラクタを書くあなたは、単にインラインコンストラクタを宣言することができます。

その後、あなたはまた、再びテンプレート代入演算子

template<typename From> 
Matrix &operator=(const Matrix<From> &f) 

を書き、これは通常の代入演算子であることをふり、および1の実施の動きを経る必要があります。