2011-06-05 144 views
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-template(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答:我不打算把它用作通用矩阵库,我想在特定的(已知的)大小的矩阵上执行操作,并想通过使用这个做法。它可以让我优化矩阵的内存布局(例如,在32字节的边界上对齐行向量)并做其他各种时髦的事情。我希望通过这样做让自己在脚下受到很多时间的伤害,但是我想要获得的主要内容是经验,并找出哪些是有效的,什么不是(以及什么是难以做到的,什么是不可行的“T)。

@Bo Perrson:我知道为什么第一个版本不能编译,但我想知道是否有我的第二次尝试可以工作的简单版本。主要问题是MyMatrix本身就是一个类模板,我需要将它的模板参数以某种方式传递给Transpose-struct。

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

回答

0

从模板定义的行/列部分获得什么?

我个人的感觉是这样做太复杂了。尽量在模板中包含数据类型,但包括尺寸似乎是错误的。

+2

他可能认为编译器可以在小矩阵上打开编码操作(从而避免循环开销),当边界是编译时常量。他可能是对的。 – Nemo 2011-06-05 17:52:53

+0

@Nemo - 啊,OK - C++不是我的东西(再多) - 所以对我来说似乎很奇怪。感谢尼莫。 – 2011-06-05 17:53:47

+1

根据您的字段,附加类型安全性也可能有用,它还允许您的基础数据结构的非堆分配。最终,更一般的解决方案通常是更好的召唤,但肯定有赞成独特类型的论点。 – 2011-06-05 18:23:37

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

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

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

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

这里,移调是一个仿函数;您创建它的一个实例,但将其称为函数。对于额外的功劳,你可以让它继承unary_function并免费获得result_type typedef ...