使用模板类作为参数专门化模板结构



我正试图通过创建一个包含矩阵和对这些矩阵的运算的库来提高我的模板技能(我知道的很少)。基本上,我希望我的矩阵是强类型的(在编译时已知数据类型和大小),并且我还希望能够自动推导转置矩阵的类型。

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字节边界上对齐行向量),并做其他一些时髦的事情。我希望通过这样做会给自己的脚开很多枪,但我想在这里获得的主要是经验,找出什么有效,什么无效(以及什么难做,什么不好做)。

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

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

是的,您正在复杂化。

如果你有这样的声明:

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

将行/列作为模板定义的一部分会带来什么好处?

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

第一次尝试失败,因为专门化是一个单独的类型,并且基础模板的模板参数在那里是未知的。

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

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

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

这里,转座是一个函子;您创建了它的一个实例,但将其作为一个函数调用。为了获得额外的积分,你可以让它从unary_function继承并免费获得result_type typedef。。。

最新更新