【问题标题】:partial specialization of a static const member variable静态 const 成员变量的部分特化
【发布时间】:2015-07-21 16:54:32
【问题描述】:

目前,我已经实现了一个模板类 Mat,它是第三方库的矩阵类的包装器(T 是组件的类型:double、int 等)。现在,我希望实现一个 Tensor 类,使用一个 Mat 用于存储,第二个 Mat 用于映射索引。

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

Tensor 类将使用 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 矩阵)。

为此,我希望我的 Tensor 类拥有矩阵:

0 5 4
5 1 3
4 3 2

如果 Dim == 3 且 Sym == true。非对称张量和二维张量(共 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...
}

在我的 Tensor 类的单元测试中,我可以输入:

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)都这样做。如果我有其他类型的张量(这里,real 是 long double 的 typdef),我会有太多重复的代码。

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

【问题讨论】:

    标签: c++ static constants partial-specialization template-classes


    【解决方案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();
    }
    

    然后只需创建一个类模板TensorMapCreator 和一个静态成员函数makeMap(),您可以根据您具体想做的事情进行部分专业化:

    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.
    

    【讨论】:

      【解决方案2】:

      我能够放弃其他答案并提出以下解决方案。在 Tensor 头文件中,我只在类定义中声明了静态 const。之后,我使用 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多