投射模板(矩阵)类

时间:2017-03-27 11:04:23

标签: c++

我有一个模板矩阵类,我希望以一种直观的方式将一种类型的实例转换为另一种类型的实例(例如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

对我来说,最直观的方法是以下两个选项之一(选项X 下面的N.B.行不编译):

#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;
}

2 个答案:

答案 0 :(得分:1)

您需要定义一个&#34;模板化复制构造函数&#34; (有点)。让我们从清理现有的构造函数开始:

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 :(得分: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>();

的无声通过

在你的ctor中使用_data.resize(_shape[0] * _shape[1]);也许是一个好主意,因为你目前有不必要的算法复杂性。