【问题标题】:specializing on a subset of types in a C++ template专注于 C++ 模板中的类型子集
【发布时间】:2011-06-03 15:17:55
【问题描述】:

我有一个关于 C++ 模板专业化的问题,希望有人能提供帮助。我有一个有 3 个模板参数的类:

template<class A, class B, class C>
class myClass {

public:
  void myFunc();
};

我想做的是编写 myFunc 的几个版本,专门用于类型 C,但对类型 A 和 B 是通用的。所以我不想要这样的完全模板化函数:

template<class A, class B, class C>
void myClass<A, B, C>::myFunc()
{
  // function code here
}

我不想要这样一个完全专业化的功能

void myClass<int, int, int>::myFunc()
{
  // code goes here
}

相反,我想做一些类似于

template<class A, class B>
void myClass<A, B, int>::myFunc()
{
  // code goes here
}

这个想法是,如果类类型 C 是 int,我会调用一个版本的 myFunc(),如果类类型 C 是 double,我会调用另一个版本的 myFunc。我已经尝试了很多不同的模板专业化语法组合(这里列出的太多了),但似乎没有一个可以编译。

有人可以在这里为我指出正确的方向吗?提前感谢您的帮助。

迈克尔

【问题讨论】:

    标签: c++ templates specialization


    【解决方案1】:

    您可以编写一个函数模板和一个重载,并将工作委托给它:

    template<class A, class B, class C>
    class myClass 
    {
       //resolver doesn't need to define anything in it!
       template<class> struct resolver {}; //empty, yet powerful!
    public:
      void myFunc() 
      {
           doFun(resolver<C>());
      }
    
      //this is a function template
      template<typename X>
      void doFun(const resolver<X> & )
      {
          //this function will get executed when C is other than int
          //so write your code here, for the general case
      }
    
      //this is an overload, not a specialization of the above function template!
      void doFun(const resolver<int> & ) 
      {
          //this function will get executed when C = int
          //so write your code here, for the special case when C = int
      }
    };
    

    注意一点:doFun(const resolve&lt;int&gt;&amp; ) 是一个重载函数,它不是函数模板的特化。您不能专门化成员函数模板如果不专门化封闭类模板。

    阅读这些文章:

    【讨论】:

    • 感谢您的回答。我想我明白发生了什么,我将尝试一下。
    【解决方案2】:

    在@Nawaz 显示的解析器类型上调度是恕我直言的最佳方式。另一种选择是将该函数的实际实现移到类之外,在它自己的结构内,使其成为静态并部分专门化结构。在课堂上,调用它。当然,如果它访问myClass的私有部分,则需要将其设为friend

    template<class A, class B, class C>
    class myClass;
    
    template<class A, class B, class C>
    struct myClassFuncs{
      typedef myClass<A,B,C> class_type;
    
      static void myFunc(class_type* self){
        // generic for everything ...
      }
    };
    
    template<class A, class B>
    struct myClassFuncs<A,B,int>{
      typedef myClass<A,B,int> class_type;
    
      static void myFunc(class_type* self){
        // specialized on C == int ...
      }
    };
    
    // and so on ...
    
    template<class A, class B, class C>
    class myClass{
      typedef myClassFuncs<A,B,C> func_holder;
      friend class func_holder;
    public:
      void myFunc(){
        func_holder::myFunc(this);
      }
    };
    

    虽然这会导致类和专用版本中有很多包装器......

    另一个可以说是相当疯狂的想法是在类中没有函数而是函子。那些得到专业化然后被调用。这更冗长,但允许更好地访问您想要专门化的功能。但是,如果他们想访问私人部分,您现在需要让他们都成为朋友。 :/

    template<class A, class B, class C>
    class myClass;
    
    template<class A, class B, class C>
    class myClass_myFunc{
      typedef myClass<A,B,C> class_type;
      class_type* const _self;
    
    public:
      myClass_myFunc(class_type* self)
        : _self(self)
      {}
    
      void operator() const{
        // generic logic here
      }
    };
    
    template<class A, class B>
    class myClass_myFunc<A,B,int>{
      typedef myClass<A,B,int> class_type;
      class_type* const _self;
    
    public:
      myClass_myFunc(class_type* self)
        : _self(self)
      {}
    
      void operator() const{
        // specialized logic here
      }
    };
    
    template<class A, class B, class C>
    class myClass{
      friend class myClass_myFunc<A,B,C>;
    public:
      myClass()
        : myFunc(this)
      {}
    
      const myClass_myFunc<A,B,C> myFunc;
    };
    

    【讨论】:

    • 如果myClassFuncs::MyFunc 访问myClass 的私有成员,那么您必须使其成为friend
    • @Nawaz - 静态成员函数可以访问类声明的私有部分。
    • @Mahesh:类的静态成员函数只能访问 那个 类的私有成员。但这里myClassFuncsmyClass 是不同的类。
    • @Nawaz:是的,我想到了那个朋友的东西,但似乎我又忘记了。已编辑。不过,我在这里有点宣传不好的做法,对吧?
    • 对于这种特殊情况,是的。但是当您需要部分专门化一组许多模板参数时,这种方法很有用,因为函数模板不能部分专门化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多