2015-07-21 64 views
0

目前,我已经实现了一个模板类Mat,它是第三方库(T是组件的类型:double,int等)的矩阵类的包装。现在,我希望实现张量类使用一个Mat存储和第二个Mat映射索引。静态const成员变量的局部特化

我将Tensor类模板化为Tensor,其中T与Mat类相同,Order和Dim是整数,是张量的顺序(或等级)和维数(2或3)。 Sym是对称性的布尔标志。

张量类将利用Voigt表示法将高阶张量压缩到矩阵上(例如,一个3乘3乘3乘3的张量可映射到6乘6矩阵;这是通过将每对索引映射到单个索引来完成的)。在Voigt表示法中,3乘3张量可以映射到6乘1的矢量(矩阵),但将张量中的(0,0)分量移动到矢量中的0位置。类似的(1,1)→1,(2,2)→2,(1,2)→3,(0,2)→4和(0,1)→5。类似的规则退出2×2张量(他们映射到3×1矩阵)。

为此,我想我的张量类拥有矩阵:

0 5 4 
5 1 3 
4 3 2 

如果暗淡== 3和符号== TRUE。有非对称张量和2D张量(共4个)的相应映射。这些不依赖于其他模板参数(T和Order)。

因此,我在什么时候专门化它们? (在这里,这个问题适用于任何有模板类的需要静态const成员才能进行部分特化的人)。

我已经在此检查了这个问题:Where to define static const member variables of a template class。但它不讨论部分专业化。

到目前为止,我有一个向前声明,并在相同的头文件中的类定义:

//cl_Tensor.hpp 
namespace myNamespace 
{ 
template< typename T, int Order, int Dim, bool Sym > 
class Tensor; 
} 

template< typename T, int Order, int Dim, bool Sym > 
class myNamespace::Tensor 
{ 
protected: 
    myNamespace::Mat< T> mMat; // storage 
    static const myNamespace::Mat <uint> mTensorMap; 

public: 
// member functions and the like... 
} 

在我的单元测试我的张量课,我可以输入:

template<> const moris::Mat< moris::uint> moris::Tensor< moris::real, 1, 2, true>::mTensorMap = { { 0, 2}, {2, 1} }; 
template<> const moris::Mat< moris::uint> moris::Tensor< moris::real, 1, 2, false>::mTensorMap = { { 0, 3}, {2, 1} }; 
template<> const moris::Mat< moris::uint> moris::Tensor< moris::real, 1, 3, true>::mTensorMap = { { 0, 5, 4}, {5, 1, 3}, {4, 3, 2} }; 
template<> const moris::Mat< moris::uint> moris::Tensor< moris::real, 1, 3, false>::mTensorMap = { { 0, 5, 4}, {8, 1, 3}, {7, 6, 2} }; 

的问题是我必须为每个订单(1,2,3和4)执行此操作。而且我应该有其他类型的张量(这里,真正的是长双倍的typdef),我会有太多重复的代码。

我在哪里可以初始化地图呢?

回答

0

我能去掉对方的回答,并用以下解决方案上来。在Tensor头文件中,我只在类定义中声明了静态常量。之后,我使用MapCreator类来模拟成员初始化。

//Tensor.hpp 
template< typename T, int Order, int Dim, bool Sym > 
class space::Tensor 
{ 
protected: 
    Mat< T> mStorageMat; 
    static const Mat < unsigned int > mTensorMap; 
public: 
    // ... 
}; 

template< typename T, int Order, int Dim, bool Sym > 
const space::Mat< unsigned int> space::Tensor<T, Order, Dim, Sym>::mTensorMatp = space::TensorMapCreator< Dim, Sym>::makeMap(); 

然后,TensorMapCreator类模板只为两个参数,我的成员变量取决于:

//TensorMapCreator.hpp 
namespace space { 
    template< int Dim, bool Sym> 
    class TensorMapCreator; 

    class TensorMapCreator< 2, true >; // specialized forward 
    class TensorMapCreator< 2, false>; // declarations 
    class TensorMapCreator< 3, true >; 
    class TensorMapCreator< 3, false>; 
} 

class space::TensorMapCreator< 2, true > 
{ 
public: 
    static 
    space::Mat< unsigned int> 
    makeMap() 
    { 
     // creates the correct map 
    } 
}; 
// 3 more specializations for the other 
// combinations of dimmension and symmetry 
1

你不能部分地专门化一个类模板的静态数据成员,但你可以像你在你的问题中说的那样明确地专门化它们。但没有什么从定义外包给其他一些函数模板阻止你:

namespace myNamespace { 
    template< typename T, int Order, int Dim, bool Sym > 
    const Tensor<T, Order, Dim, bool>::Mat<Dim> mTensorMap = 
     TensorMapCreator<T, Order, Dim, Sym>::makeMap(); 
} 

然后,它只是一个带有静态成员函数makeMap()创建一个类模板TensorMapCreator的事情,你可以根据它是什么部分专业你特别想做的事:

template <typename T, int Order, int Dim, bool Sym> 
struct TensorMapCreator; 

template <typename T, int Order, bool Sym> 
struct TensorMapCreator<T, Order, 2, Sym> { 
    static Mat<2> makeMap(); 
}; 

template <typename T, int Order, bool Sym> 
struct TensorMapCreator<T, Order, 3, Sym> { 
    static Mat<3> makeMap(); 
}; 

// etc.