【问题标题】:Is it possible to access values of non-type template parameters in specialized template class?是否可以在专用模板类中访问非类型模板参数的值?
【发布时间】:2009-07-22 00:08:03
【问题描述】:

是否可以在专门的模板类中访问非类型模板参数的值?

如果我有专门化的模板类:

   template <int major, int minor> struct A {
       void f() { cout << major << endl; }
   }

   template <> struct A<4,0> {
       void f() { cout << ??? << endl; }
   }

我知道在上述情况下,硬编码值 4 和 0 而不是使用变量很简单,但是我有一个更大的类,我正在专门研究它,我希望能够访问这些值。

是否可以在 A 中访问 majorminor 值(4 和 0)?还是我必须在模板实例化时将它们分配为常量:

   template <> struct A<4,0> {
       static const int major = 4;
       static const int minor = 0;
       ...
   }

【问题讨论】:

  • 如果您基于价值观进行专业化,那么这意味着这些特定价值观有一些特别之处。如果您在整个模板中将它们用作通用值,并且只在少数地方将它们视为特殊的,那么您可能可以将特殊行为抽象为一个较小的专用类模板,而使大模板完全通用且非专用。这有点难说,所以你能把你的问题扩大到更“真实”吗?
  • 我认为这个问题足够真实。我有现有的基类,它根据协议版本实现特定行为。以前它有一个返回协议版本的成员 - 由于该成员不再可用,因此有一个日志记录方法在输出中包含协议版本。我可以对值进行硬编码,但我想知道是否有更好的方法。接受的答案提供了很好的方法 - 我实际上在其他地方以类似的方式使用特征 - 用于获取参数类型但意图是相同的。

标签: c++ templates template-specialization


【解决方案1】:

这类问题可以通过使用一组单独的“特征”结构来解决。

// A default Traits class has no information
template<class T> struct Traits
{
};

// A convenient way to get the Traits of the type of a given value without
// having to explicitly write out the type
template<typename T> Traits<T> GetTraits(const T&)
{
    return Traits<T>();
}

template <int major, int minor> struct A 
{ 
    void f() 
    { 
        cout << major << endl; 
    }   
};

// Specialisation of the traits for any A<int, int>
template<int N1, int N2> struct Traits<A<N1, N2> >
{
    enum { major = N1, minor = N2 };
};

template <> struct A<4,0> 
{       
    void f() 
    { 
        cout << GetTraits(*this).major << endl; 
    }   
};

【讨论】:

    【解决方案2】:

    不是你问题的真正答案,但你可以列举它们,即:

    enum{
     specialisationMajor=4,
     specialisationMinor=0
    };
    
    template <> struct A<specialisationMajor,specialisationMinor> {
        static const int major = specialisationMajor;
        static const int minor = specialisationMinor;
        ...
    }
    

    【讨论】:

    • 我试图避免定义另一组变量......这是拥有这些模板参数的美妙之处,我通常不想访问这些值......但没关系,但是谢谢
    【解决方案3】:

    不是你的问题的真正答案,但下面的想法帮助了我一次:

    #include <iostream>
    
    template <int major, int minor, int= major, int= minor> struct A {
        void f() { std::cout << major << '\n'; }
    };
    
    template <int major, int minor> struct A<major, minor, 4, 0> {
        void f() { std::cout << major << ':' << minor << '\n'; }
    };
    
    int main()
    {
        A<3, 3>().f();
        A<4, 0>().f();
    }
    

    【讨论】:

      【解决方案4】:

      不,您无权访问专门的非类型模板参数。但是这里有一个方法,在f的实现中不要重复自己:

         template <int major, int minor>
         struct f_impl
         {
             void f() { cout << major << endl; }
         };
      
         template <int major, int minor>
         struct A : public f_impl<major, minor>
         {};
      
         template <> struct A<4,0> : public f_impl<4,0>
         {};
      

      对于这个例子,一个人不会获得太多,因为一个人需要写两次4,0(--所以你可以在你的 OP 中的cout 中写第二次)。但是,如果您使用模板参数有更多功能,它就会开始付出代价。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-23
        • 1970-01-01
        • 2018-02-28
        • 2021-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多