2015-07-21 66 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.