3

我试图通过创建一个包含矩阵和对这些矩阵的操作的库来塑造我的模板技能(我知道的很少)。基本上,我希望我的矩阵是非常强类型的(数据类型和大小在编译时已知),并且我还希望能够自动扣除转置矩阵的类型。

template< typename TDataType, size_t rows, size_t cols > class MyMatrix

矩阵可以嵌套,因此TDataType可以是整数类型,也可以是单独的MyMatrix<...>,导致转置矩阵的数据类型不一定与原始矩阵的数据类型相同,例如:( Transpose( MyMatrix< MyMatrix< char, 2, 3 >, 4, 6 > ) ==> MyMatrix< MyMatrix< char, 3, 2 >, 6, 4 >外层矩阵的数据类型已更改)

我第一次尝试转置类型演绎是:

template< typename TDataType >
struct Transpose
  {
  typedef TDataType type;
  };

template<>
struct Transpose< MyMatrix<TDataType, rows, cols> >
  {
  typedef MyMatrix<typename Transpose<TDataType>::type, cols, rows> type;
  };

我没有找到这样做的方法,因为我似乎无法使用 MyMatrix 专门化 Transpose 模板(TDataType 未知和类似错误)。

我想出的唯一可编译的解决方案(我什至不知道它是否有效)是这样的:

template< typename TMatrixType, typename TDataType, size_t rows, size_t cols >
struct Transpose
  {
  typedef TMatrixType type;
  };

template< typename TDataType, size_t rows, size_t cols >
struct Transpose< MyMatrix<TDataType, rows, cols>, TDataType, rows, cols >
  {
  typedef MyMatrix< typename Transpose<TDataType,TDataType,rows,cols>::type, cols, rows > type;
  };

我相信我把事情弄得太复杂了;有没有更简单的解决方案来实现我想要的?


我的问题的答案的答案(我发布了没有帐户的问题,所以我没有足够的代表以正常方式做事)。已经非常感谢了!

@Bo Persson @Will A:我不打算将其用作通用矩阵库,我想对特定(事先已知)大小的矩阵执行操作,并想看看我可以通过使用这种方法获得什么。它可能允许我优化矩阵的内存布局(例如在 32 字节边界上对齐行向量)并做其他类型的时髦的东西。我希望通过这样做很多次,但我想要达到的主要目的是体验并找出哪些有效,哪些无效(以及什么是难做的,什么是难做的) 't)。

@Bo Perrson:我知道为什么第一个版本无法编译,但我想知道我的第二次尝试是否有一个更简单的版本可以工作。主要问题是 MyMatrix 本身就是一个类模板,我需要以某种方式将它的模板参数获取到转置结构。

@VJo:我认为这行不通。如果 T 是 MyMatrix<..> 本身,则转置矩阵应该具有Transpose<T> 数据类型,而不是 T 本身。对于所有基本类型(char、int、double ...),这当然是正确的并且更简单。

4

4 回答 4

3

是的,你很复杂。

如果你有这样的声明:

template< typename TDataType, size_t rows, size_t cols > class MyMatrix

那么转置函数应该是这样的:

template< typename T, size_t rows, size_t cols >
MyMatrix< T, cols, rows > Transpose( const MyMatrix< T, rows, cols > & m )
{
  MyMatrix< T, cols, rows > res;
  // implementation
  return res;
}
于 2011-06-05T17:42:37.100 回答
0

第一次尝试失败,因为特化是一个单独的类型,并且基本模板的模板参数在那里不知道。

根据语言,第二个版本是正确的,但就像 Will A 说的那样 - 你真的希望 row 和 col 的每个组合都创建一个新类型吗?

于 2011-06-05T17:42:59.120 回答
0

我会这样写,以允许任意深度的递归(矩阵矩阵的矩阵......)

template<typename T, unsigned rows, unsigned cols>
struct MyMatrix
{
  typedef T value_type;
  T stuff[rows][cols];  // or whatever                                      
};

// For basic types, transpose is identity.                                  
template<typename T>
struct Transpose {
  typedef T result_type;
  result_type operator()(const T & in) {
    return in;
  }
};

// For more complex types, specialize and invoke recursively.
template<typename T, unsigned rows, unsigned cols>
struct Transpose<MyMatrix<T, rows, cols> > {
  typedef MyMatrix<Transpose<T>, cols, rows> result_type;
  result_type operator()(const MyMatrix<T, rows, cols> & in) {
    Transpose<T> transposer;
    // (invoke transposer on each element of in and build result)           
  }
};

这里,Transpose 是一个函子;您创建它的一个实例,但将其作为函数调用。为了获得额外的功劳,您可以让它继承unary_function并免费获得result_typetypedef ...

于 2011-06-05T20:06:26.330 回答
0

将行/列作为模板定义的一部分,您有什么收获?

我个人的感觉是,这让事情变得太复杂了。一定要在模板中包含数据类型,但包含维度似乎是错误的。

于 2011-06-05T17:32:53.050 回答