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

时间:2011-06-05 17:29:45

标签: c++ templates specialization

我正在尝试通过在这些矩阵上创建包含矩阵和操作的库来塑造我的模板技能(我知之甚少)。基本上,我希望我的矩阵是非常强类型的(数据类型和大小在编译时已知),我也希望能够自动推导出转置矩阵的类型。

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本身就是一个类模板,我需要以某种方式将它的模板参数传递给Transpose-struct。

@VJo:我认为这不会奏效。如果T是MyMatrix&lt; ..&gt;然后转置矩阵应该有Transpose<T>作为数据类型,而不是T本身。对于所有基本类型(char,int,double ...),这当然是正确的,也更简单。

4 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

将row / cols作为模板定义的一部分会得到什么?

我个人的感觉是,这使事情过于复杂。通过包括模板中的数据类型,但包括维度似乎是错误的。

答案 2 :(得分:0)

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

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

答案 3 :(得分: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_type typedef ...