3

C++ でのテンプレートの特殊化について質問があります。誰かが助けてくれることを願っています。3 つのテンプレート パラメーターを持つクラスがあります。

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

public:
  void myFunc();
};

私がやりたいことは、たとえばタイプ C に特化しているが、タイプ A と B には一般的な myFunc のいくつかのバージョンを作成することです。したがって、次のような完全にテンプレート化された関数は必要ありません。

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() の 1 つのバージョンを呼び出し、クラス型 C が double の場合、myFunc の別のバージョンを呼び出すという考え方です。テンプレートの特殊化構文のさまざまな組み合わせ (ここにリストするには多すぎる) をたくさん試しましたが、どれもコンパイルできないようです。

誰かがここで私を正しい方向に向けることができますか? よろしくお願いします。

マイケル

4

2 に答える 2

6

関数テンプレートとオーバーロードを記述し、それに作業を委任できます。

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<int>& )はオーバーロードされた関数であり、関数テンプレートの特殊化ではありません。外側のクラス テンプレートを特殊化せずにメンバー関数テンプレートを特殊化することはできません。

これらの記事を読んでください:

于 2011-06-03T15:26:04.610 に答える
0

@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);
  }
};

それはクラスと特殊化されたバージョンの多くのラッパーにつながりますが...

かなりクレイジーとも言えるもう 1 つのアイデアは、クラスに関数ではなくファンクターを持たせることです。それらは特殊化されてから呼び出されます。これはより冗長ですが、特化したい関数へのより良いアクセスを可能にします。ただし、プライベート パーツにアクセスしたい場合は、すべてのユーザーを友達にする必要があります。:/

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;
};
于 2011-06-03T15:35:46.600 に答える