我正在尝试通过创建一个包含矩阵和对这些矩阵的操作的库来提高我的模板技能(我知之甚少)。基本上,我希望我的矩阵具有非常强的类型(在编译时已知的数据类型和大小),并且我还希望能够自动推断转置矩阵的类型。
模板<类型名TDataType,size_t行,size_t列> class MyMatrix
矩阵可以嵌套,因此 TDataType
可以是整型,但它本身也是一个 MyMatrix<...>
,导致数据类型为转置矩阵不一定与原始矩阵相同,例如:
Transpose( MyMatrix, 4, 6 > ) ==>我的矩阵我的矩阵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;
};
我找不到这样做的方法,因为我不能' t 似乎专门使用 MyMatrix 转置模板(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 结构。
@VJo:我认为这行不通。如果T是MyMatrix<...>那么转置矩阵应该将 Transpose 作为数据类型,而不是 T 本身。对于所有基本类型(char、int、double...),这当然是正确的并且更简单。
I'm trying to shape up my template skills (I know very little) by creating a library containing matrices and operations on those matrices. Basically, I want my matrix to be very strongly typed (datatype and size known at compile-time) and I also want to be able to automatically deduct the type of the transpose matrix.
template< typename TDataType, size_t rows, size_t cols > class MyMatrix
Matrices can be nested, so TDataType
can be an integral type, but also a MyMatrix<...>
by itself, causing the datatype for a transposed matrix to be not necessarily the same as the one of the original matrix, e.g:
Transpose( MyMatrix< MyMatrix< char, 2, 3 >, 4, 6 > ) ==> MyMatrix< MyMatrix< char, 3, 2 >, 6, 4 >
(the datatype of the outer matrix has changed)
My first attempt for transposed-type-deduction was:
template< typename TDataType >
struct Transpose
{
typedef TDataType type;
};
template<>
struct Transpose< MyMatrix<TDataType, rows, cols> >
{
typedef MyMatrix<typename Transpose<TDataType>::type, cols, rows> type;
};
I have found no way of doing this because I can't seem to specialize the Transpose-template with MyMatrix (TDataType unknown and similar errors).
The only compilable solution I've come up with (I don't even know if it works yet) is this:
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;
};
I believe I am making things too complicated; is there an easier solution to achieve what I want?
An answer to the answers to my question (I posted the question without an account, so I don't have enough rep to do things the normal way). Thanks a lot already!
@Bo Persson @Will A : I do not intend to use this as a general purpose matrix library, I want to perform operations on matrices of specific (known beforehand) sizes and want to see where I can get by using this approach. It may allow me to optimize memory-layout for matrices (e.g. align row-vectors on 32-byte boundaries) and do other sorts of funky stuff. I expect to shoot myself in the foot an awful lot of times by doing this, but the main thing I'm trying to get here is experience and find out what works and what doesn't (and what is hard to do and what isn't).
@Bo Perrson : I know why the first version doesn't compile, but I was wondering if there was a simpler version of my second try that could work. Main problem is that MyMatrix is a class template itself and I need to get the template arguments of it somehow to the Transpose-struct.
@VJo : I don' t think that would work. If T is a MyMatrix<..> itself then the transpose matrix should have Transpose<T>
as a datatype, not T itself. For all basic types (char, int, double...), this is of course correct and way simpler.
发布评论
评论(4)
是的,你让事情变得复杂了。
如果你有这样的声明:
那么转置函数应该是这样的:
Yes, you are complicating.
If you have declaration like this :
then the transpose function should be like this :
将行/列作为模板定义的一部分可以得到什么?
我个人的感觉是,这让事情变得太复杂了。无论如何,在模板中包含数据类型,但包含维度似乎是错误的。
What do you gain from making the rows / cols part of the template definition?
My personal feeling is that this is making things way too complex. By all means include the data type in the template, but including the dimensions seems wrong.
第一次尝试失败,因为特化是一种单独的类型,并且基本模板的模板参数在那里未知。
根据语言,第二个版本是正确的,但就像 Will A 所说的那样 - 你真的希望 row 和 col 的每个组合都创建一个新类型吗?
The first attempt fails because the specialization is a separate type and the template parameters of the base template are not known there.
The second verision is correct according to the language, but like Will A says - do you really want every combination of row and col to create a new type?
我会这样写,以允许任意深度的递归(矩阵的矩阵的矩阵......)
这里,Transpose 是一个函子;您创建它的一个实例,但将其作为函数调用。为了获得额外的积分,您可以让它继承
unary_function
并免费获得result_type
typedef...I would write it something like this, to allow arbitrary depths of recursion (matrices of matrices of matrices...)
Here, Transpose is a functor; you create an instance of it but call it as a function. For extra credit, you could have it inherit from
unary_function
and get theresult_type
typedef for free...