Можно ли специализироваться на некоторых (не всех) параметрах шаблона класса? - PullRequest
2 голосов
/ 08 февраля 2010

Можно ли специализироваться на некоторых (не всех) параметрах шаблона класса?

Например:

template <typename T, typename U>
class TC
{
public:
 void Foo();
};

template <typename T, typename U>
void TC<T, U>::Foo()
{

}

template <???, typename U>
void TC<int, U>::Foo()
{
  //Want this defined for all U but only when T is int.
}

int main(int argv, char * args [])
{
 TC<int, char> tc;
 return 0;
}

Ответы [ 3 ]

3 голосов
/ 08 февраля 2010

Как правило, вы можете специализировать только некоторые параметры шаблона шаблона класса, это называется "частичной специализацией".При этом вы создаете новую специализированную версию шаблона, которая «переопределяет» общую версию.

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

// specialization for T=int
template <typename U>
class TC<int, U> {
public:
  void Foo();
};

// implementation of Foo() for the specialized template
template <typename U>
void TC<int, U>::Foo()
{
  //Want this defined for all U but only when T is int.
}
1 голос
/ 08 февраля 2010

Для занятий да. Для функций нет и да.

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

Для классов вы просто опускаете специализированные аргументы из списка параметров шаблона и включаете его в определение класса:

// General template class for a vector
template <class T, int N>
struct Vector
{
  T e[N];
};

// Specialization for N=3
template <class T> // omit the N
struct Vector<T, 3> // and include it here
{
  T e[3];

  static Vector<T, 3> cross(const Vector<T, 3>& a, const Vector<T, 3>& b)
  {
    return Vector<T, 3>( a.e[1] * b.e[2] - a.e[2] * b.e[1],
                         a.e[2] * b.e[0] - a.e[0] * b.e[2],
                         a.e[0] * b.e[1] - a.e[1] * b.e[0] );

  }
};

Для глобальных функций вы не можете этого сделать. Вы можете определить функцию, которая является полностью общей, или полностью специализированной - частичная специализация функций запрещена.

Однако вы можете частично специализировать функцию, создав ее в качестве прокси для статической функции частично специализированного класса.

1012 *, например *

template <class A, class B>
void foo(A a, B b)
{
  foo_impl::fun(a, b);
}

template <class A, class B>
struct foo_impl
{
  static void fun(A a, B b)
  {
    // real implementation here
  }
};

Затем вы можете специализировать foo_impl по своему усмотрению, что будет отражено в foo.

0 голосов
/ 08 февраля 2010

Если вы хотите специализировать только часть класса, вам нужен оригинальный класс для обеспечения хуков.Обычно он описывается как Traits или Policies в зависимости от реализации.

Класс Traits - это класс, который ссылается на некоторые свойства, а иногда и методы, для данного типа и не передается явно.Примером в STL является std::iterator_traits<It>.

A Policy класс - это класс, передаваемый в качестве параметра шаблона, который используется для реализации ряда функциональных возможностей.Примером в STL является std::less<int> в std::set<int, std::less<int> >.

Как правило, использование Policy класса является явным, в то время как использование Traits является неявным ... и поэтому я предпочитаюот первого к последнему.

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

...