矩阵

时间:2016-07-12 09:10:54

标签: c++ templates matrix

我实现了这样的模板矩阵类。

template<typename T, int NRows, int NCols>
class MatrixMN;

但是现在我怀疑用模板实现矩阵是正确的选择,原因如下。

1。 operator*=无法定义

这是因为矩阵乘法的 * =运算符可能会返回具有不同维度的矩阵类型。

不同的维度在模板实现中意味着不同的类型。

2。不能为具有不同T参数

的两个MatrixMN定义算术运算符

让我们为矩阵乘法定义一个二元运算符。

template <typename T1, int NRows1, int NCols1, typename T2, int NRows2, int NCols2>
MatrixMN<??, NRows1, NCols2> operator*(const MatrixMN<T1, NRows1, NCols1> &m1, const MatrixMN<T2, NRows2, NCols2> &m2)

T1T2可能是{intdouble}或{doubleint}。

所以我无法决定返回T的{​​{1}}参数。

我提出了一些解决方法。

  • 强制返回的MatrixMN具有MatrixMN
  • 等浮点数据类型
  • 只是不要为两个不同的double参数定义运算符。

但是没有一个能够完美地解决问题......

像这样实现矩阵类是不对的?

2 个答案:

答案 0 :(得分:2)

您可以将operator*限制为仅适用于相同类型的矩阵,并且您知道结果大小:m-by-n乘以n-by-k会得到m-by-k矩阵。把它放在一起就可以了:

template<typename T, int M, int N, int K>
MatrixMN<T, M, K> operator*(const MatrixMN<T, M, N> &lhs, const MatrixMN<T, N, K> &rhs)

如果您只想允许隐式可转换类型,请使用std::common_type

// Arithmetic operation allowing for implicitly convertible types
template<typename TL, typename TR, int M, int N, int K>
MatrixMN<typename std::common_type<TL, TR>::type, M, K> operator*(
        const MatrixMN<TL, M, N> &lhs,
        const MatrixMN<TR, N, K> &rhs)

如果您想允许您定义的任何类型组合,那就是traits的用途:

template<typename LHS, typename RHS, typename RES>
struct MatrixMNBinaryTraitsBase {
    typedef LHS TypeLeft;       // Element type of left hand side
    typedef RHS TypeRight;      // Element type of right hand side
    typedef RES TypeMultResult; // Element type of matrix multiplication
};

// Base case: support for implicitly convertible types
template<typename TL, typename TR>
struct MatrixMNBinaryTraits : MatrixMNBinaryTraitsBase<TL, TR, typename std::common_type<TL, TR>::type> { };

// Special case Foo x Bar -> Foobar
template<>
struct MatrixMNBinaryTraits<Foo, Bar> : MatrixMNBinaryTraitsBase<Foo, Bar, Foobar> { };

// Arithmetic operation allowing for different types according to MatrixMNBinaryTraits
template<typename TL, typename TR, int M, int N, int K>
MatrixMN<typename MatrixMNBinaryTraits<TL, TR>::TypeMultResult, M, K> operator*(
        const MatrixMN<TL, M, N> &lhs,
        const MatrixMN<TR, N, K> &rhs)

答案 1 :(得分:2)

您的运算符可以定义为具有良好维度和良好基础类型的矩阵(即T1T2,以便有效operator*T1T2及其类型已定义operator+

template <typename T1, typename T2>
using multiply_type = decltype(std::declval<T1>()*std::declval<T2>());

template <typename T1, typename T2, int N, int K, int M>
auto operator*(Matrix<T1, N, K> const& m1, Matrix<T2, K, M> const& m2)
    -> Matrix<multiply_type<T1, T2>, M, N> {
    /* Implementation of the product */
}

这比std::common_type的限制性要小,但你不太可能在非算术类型上构建矩阵(但如果是?)

可以看到此技术在Coliru上运行。