11

テンプレート クラス メソッドの部分的な特殊化はありますか?

 template <class A, class B>
 class C
 {
  void foo();
 }

次のように特殊化しても機能しません。

template <class A> void C<A, CObject>::foo() {};

何か助けはありますか?

4

5 に答える 5

12

特殊化されたクラスが既にある場合はfoo、特殊化されたクラスで別の実装を行うことができます。

template<typename A, typename B>
class C
{
public:
    void foo() { cout << "default" << endl; };
};

template<typename A>
class C<A, CObject>
{
public:
  void foo() { cout << "CObject" << endl; };
};

Visual C++ 2008 でメンバー関数を特殊化するには、テンプレートにすることもできます。

template<typename A, typename B>
class C
{
  template<typename T>
  void foo();

  template<>
  void foo<CObject>();
};

上記のソリューションは、将来の C++ 標準でのみ利用できるようです (ドラフト n2914 14.6.5.3/2 によると)。

于 2009-10-08T05:56:57.650 に答える
8

そこに誤解があると思います。

テンプレートには次の 2 種類があります。

  • テンプレートクラス
  • テンプレートメソッド

あなたの例では、もちろんいくつかのメソッドを含むテンプレート クラスがあります。この場合、クラスを特化する必要があります。

template <class A>
class C<A,CObject>
{
  void foo() { ... } // specialized code
};

あなたの例の問題は比較的単純です。特殊化 C のメソッド foo を定義しますが、この特殊化は事前に宣言されていません。

ここでの問題は、C クラスを完全に特殊化する必要がある (したがって、大量のデータをコピーする) ことです。いくつかの回避策があります。

  • 継承 (構成 ?): 基本クラスですべての一般的な作業を行い、次に C クラスを継承させ、必要に応じて特殊化します。
  • フレンド: 「foo」メソッドを C のメンバーにする代わりに、フレンド フリー関数として定義し、このメソッドのみを特殊化します。
  • 委譲: 'foo' メソッドに、フリー関数である別のメソッド 'bar' を呼び出させ、'bar' を適切に特殊化します。

コードでは次のようになります。

// 1- Inheritance
template <class A, class B>
class CBase
{
  // Everything that does not require specialization
};

template <class A, class B>
class C: public CBase<A,B>
         // depending on your need, consider using another inheritance
         // or even better, composition
{
  void foo(); // generic
};

template <class A>
class C<A,CObject> : public CBase<A,CObject>
{
  void foo(); // specialized
};

// 2- Friend
// note the change in signature:
// - now you need to pass the attributes to be changed
// - the last parameter helps differentiating the overload
//   as there is no specialization for functions
template <class A, class B> void foo(Arg1&, Arg2&, const B&);
template <class A> void foo(Arg1&, Arg2&, const CObject&);

template <class A, class B>
class C
{
  friend template <class, class> foo;
};

// 3- Delegation
// same signature as foo in (2)
template <class A, class B> void bar(Arg1&, Arg2&, const B&);
template <class A> void bar(Arg1&, Arg2&, const CObject&);

template <class A, class B>
class C
{
  void foo() { bar(member1, member2, B()); }
};

それが明確になり、役立つことを願っています!

于 2009-10-08T06:23:39.120 に答える
2

いいえ、追加される C++0x の部分的な関数テンプレートの特殊化はありません。

上で正しく述べたように、関数テンプレートに関しては、基本的に 2 つのことが行われました。

  • デフォルトのテンプレート引数が利用可能になりました。
  • 可変個引数テンプレートが導入されました。

そのため、以前と同様に、部分的な関数テンプレートの特殊化を「エミュレート」するために回避策を使用する必要があります。

于 2009-10-14T07:20:48.513 に答える
1

クラスはテンプレートであるため、次のことを特殊化する必要があります。

template <class A>
class C<A, CObject> 
{
   void foo() { ... }
}
于 2009-10-08T05:51:23.270 に答える
0

私の記憶が正しければ、関数に対して部分的なテンプレートの特殊化を行うことはできません。C++0X に含まれているかどうか不明

更新: (確認待ち)コメントに記載されているように、関数の部分的なテンプレートの特殊化は C++0X で可能です。

于 2009-10-08T05:53:31.490 に答える