C++ 隐式转换类模板

C++ 隐式转换类模板,c++,c++11,templates,type-conversion,C++,C++11,Templates,Type Conversion,我试图用线性代数运算实现一个矩阵类。我想使该类可用于一些值类型,如uint,uchar,float,double 标题如下所示: template<typename T> class Matrix{ public: Matrix(int width, int height); Matrix(const Matrix<T> & other); virtual ~Matrix(); unsigned int width() const

我试图用线性代数运算实现一个矩阵类。我想使该类可用于一些值类型,如
uint
uchar
float
double

标题如下所示:

template<typename T>
class Matrix{
public:
    Matrix(int width, int height);
    Matrix(const Matrix<T> & other);
    virtual ~Matrix();
    unsigned int width() const { return width_; }
    unsigned int height() const { return height_; };
    T * data() const { return data_ptr_; };
private:
  T * data_ptr_;
  unsigned int width_;
  unsigned int height_;
}
我希望能够在没有显式转换的情况下做到这一点。比如说

Matrix<float> float_matrix(10,20);
Matrix<int> int_matrix(10,20);

auto sum_matrix = float_matrix + int_matrix;
并定义隐式构造函数,如

//inside the class declaration
template<typename K>
Matrix(const Matrix<K> & other);
并为每种情况编写专门化,但是,我无法让编译器正确推断模板参数

这两种方法似乎都不正确


有人能给我指个方向吗?

您可以使用方法3和C++11的自动返回类型推断来为您确定类型。使用

template<typename K>
auto operator+(const Matrix<K> &other) const -> Matrix<decltype(std::declval<T>() + std::declval<K>())>;
模板
自动运算符+(常数矩阵和其他)常数->矩阵;
这表示返回的矩阵将具有添加到
K
T
类型


您将无法使用此方法创建自定义规则,但它将遵循标准的升级/转换规则。

您可以使用方法3并使用C++11的自动返回类型推断为您确定类型。使用

template<typename K>
auto operator+(const Matrix<K> &other) const -> Matrix<decltype(std::declval<T>() + std::declval<K>())>;
模板
自动运算符+(常数矩阵和其他)常数->矩阵;
这表示返回的矩阵将具有添加到
K
T
类型


您将无法使用此方法创建自定义规则,但它将遵循标准的升级/转换规则。

MathanOliver方法3的变体:定义
运算符+()
(主题外建议:是否将
运算符+=()
定义为方法,将
运算符+()
定义为外部函数)不是作为方法,而是作为外部函数(如果需要,您可以使其成为矩阵的朋友)


MathanOliver方法3的变体:定义
运算符+()
(非主题建议:曾经将
运算符+=()
定义为方法,将
运算符+()
定义为外部函数)而不是方法,而是外部函数(如果需要,您可以将其定义为
矩阵的朋友)


非常感谢你@瓦哈根,不客气。希望这会让你的生活更轻松。非常感谢你@瓦哈根,不客气。希望这能让你的生活更轻松。
//inside the class declaration
template<typename K>
Matrix(const Matrix<K> & other);
//inside the class declaration
template<typename K, typename R>
Matrix<R> operator+(const Matrix<K> &other) const;
template<typename K>
auto operator+(const Matrix<K> &other) const -> Matrix<decltype(std::declval<T>() + std::declval<K>())>;
template <typename T1, typename T2,
          typename Tr = decltype(std::declval<T1>() + std::declval<T2>())>
Matrix<Tr> operator+ (Matrix<T1> const & m1, Matrix<T2> const & m2)
 { 
   // something useful
   return {m1.width(), m1.height()};
 }
#include <cstring>
#include <utility>

template <typename T>
class Matrix
 {
   public:
      Matrix(unsigned int width, unsigned int height)
         : width_(width), height_(height)
       { data_ptr_ = new T[width * height]; }

      Matrix(const Matrix<T> & other)
         : Matrix(other.width(), other.height() )
       { std::memcpy(data_ptr_, other.data(), width_ * height_ * sizeof(T)); }
      virtual ~Matrix()
       { delete []data_ptr_; }
      unsigned int width() const
       { return width_; }
      unsigned int height() const
       { return height_; };
      T * data() const
       { return data_ptr_; };
   private:
      T * data_ptr_;
      unsigned int width_;
      unsigned int height_;
 };

template <typename T1, typename T2,
          typename Tr = decltype(std::declval<T1>() + std::declval<T2>())>
Matrix<Tr> operator+ (Matrix<T1> const & m1, Matrix<T2> const & m2)
 {
   return {m1.width(), m1.height()};
 }


int main ()
 {
   Matrix<int>   m1{1, 2};
   Matrix<float> m2{1, 2};

   auto m3 = m1 + m2;
   auto m4 = m2 + m1;

   static_assert( std::is_same<decltype(m3), Matrix<float>>{}, "!" );
   static_assert( std::is_same<decltype(m4), Matrix<float>>{}, "!" );

   return 0;
 }
auto m5 = operator+<int, float, int>(m1, m2);

static_assert( std::is_same<decltype(m5), Matrix<int>>{}, "!" );