Частичная специализация C ++ - PullRequest
11 голосов
/ 08 октября 2009

Есть ли частичная специализация для метода класса шаблона?

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

это не работает, чтобы специализировать это так:

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

Любая помощь?

Ответы [ 5 ]

12 голосов
/ 08 октября 2009

Если у вас уже есть специализированный класс, вы можете указать другую реализацию 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).

8 голосов
/ 08 октября 2009

Я думаю, что там есть недоразумение.

Существует два вида шаблонов:

  • шаблон классов
  • шаблонные методы

В вашем примере у вас есть шаблонный класс, который, конечно, содержит несколько методов. В этом случае вам придется специализировать класс.

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

Проблема в вашем примере относительно проста: вы определяете метод foo для специализации C, но эта специализация никогда не была заранее объявлена ​​.

Проблема здесь в том, что вы должны полностью специализировать свой класс C (и, следовательно, копировать много данных). Есть несколько обходных путей.

  • Наследование (Композиция?): Выполнять всю обычную работу в базовом классе, затем наследовать класс C и специализировать в зависимости от ситуации
  • Friend: вместо того, чтобы метод '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()); }
};

Надеюсь, это прояснит и поможет!

2 голосов
/ 14 октября 2009

Нет, в C ++ 0x нет частичной специализации шаблона функции.

Как правильно упомянуто выше, в отношении шаблонов функций в основном было сделано 2 вещи:

  • аргументы шаблона по умолчанию стали доступны;
  • Введены вариационные шаблоны.

Так же, как и раньше, для «эмуляции» частичной специализации шаблонов функций следует использовать обходные пути.

1 голос
/ 08 октября 2009

Так как класс является шаблоном, вам нужно специализировать это:

template <class A>
class C<A, CObject> 
{
   void foo() { ... }
}
0 голосов
/ 08 октября 2009

Если я правильно помню, вы не можете сделать частичную специализацию шаблона для функций. Не уверен, включен ли он в C ++ 0X

Обновление: (Ожидание подтверждения) Как отмечено в комментариях, частичная специализация шаблонов функций возможна в C ++ 0X.

...