Специализация частичных методов C ++

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

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

не получится специализировать его вот так:

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

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


person faya    schedule 08.10.2009    source источник
comment
В других ответах показано несколько способов: stackoverflow.com/questions/1501357/   -  person Johannes Schaub - litb    schedule 08.10.2009


Ответы (5)


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

person Kirill V. Lyadvinsky    schedule 08.10.2009
comment
Хотя второе верно, первое неверно - вы не можете поместить явную специализацию в область класса - и даже если вы поместите специализацию шаблона в область пространства имен - если вы специализируете шаблон, то все его включающие шаблоны также должны быть специализированы :( Так что придется придерживаться второго пути. - person Johannes Schaub - litb; 08.10.2009
comment
Таким образом, это не сработает, например: template<typename A, typename B> template<> void C<A, B>::foo<CObject>() { }, потому что, хотя шаблон функции-члена является специализированным, внешний еще не является. Вы могли бы сделать наоборот template<> template<typename T> void C<int, bool>::foo() { }, но я подозреваю, что он не этого хочет -.- - person Johannes Schaub - litb; 08.10.2009
comment
Сначала кажется, что он не соответствует стандарту C ++ 03, но он работает в Visual C ++ 2008. Это похоже на расширение C ++ 0x (14.6.5.3 Члены специализаций шаблонов классов). - person Kirill V. Lyadvinsky; 08.10.2009
comment
Фиксированный ответ, второй вариант все еще существует для справки. - person Kirill V. Lyadvinsky; 08.10.2009
comment
Пример 14.6.5.3/2 в черновике c ++ 0x является частичной специализацией. Для частичных специализаций этих ограничений нет. Их можно поместить в область действия класса - уже в C ++ 03. Но в вашем случае вы явно специализируете шаблон функции. Если бы они сделали это в своем примере, это тоже было бы незаконным: template<class T> struct A { template<class T2> struct B {}; template<> struct B<int*> {}; };. Отчет о проблеме есть на open-std.org/ jtc1 / sc22 / wg21 / docs / cwg_closed.html # 727 с просьбой снять это ограничение (что, конечно, я тоже приветствую) - person Johannes Schaub - litb; 08.10.2009

Думаю, тут недоразумение.

Есть два вида шаблонов:

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

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

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

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

Проблема здесь в том, что вам нужно полностью специализировать свой класс 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()); }
};

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

person Matthieu M.    schedule 08.10.2009

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

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

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

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

person Community    schedule 14.10.2009

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

template <class A>
class C<A, CObject> 
{
   void foo() { ... }
}
person R Samuel Klatchko    schedule 08.10.2009
comment
У меня уже есть специализированный класс, но мне как раз нужен специализированный метод :) - person faya; 08.10.2009

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

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

person Yngve Hammersland    schedule 08.10.2009
comment
Это ограничение снято на C ++ 0x - person the_drow; 08.10.2009
comment
@yngvedh, у вас есть ссылка на это обновление: примечание? Я еще не слышал об этом. Afaik, они просто отменяют аргументы по умолчанию - то есть вы можете иметь аргументы по умолчанию в шаблонах функций. - person Johannes Schaub - litb; 08.10.2009
comment
@libt, ссылки нет. Я просто предположил, что the_drow знает, о чем говорит, поскольку я не эксперт по C ++ 0X. Может кто-нибудь в курсе подтвердить это? Я обновлю соответственно. - person Yngve Hammersland; 08.10.2009