views:

63

answers:

3

For example:

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

Thanks very much!

+3  A: 

Generally you can specialize just some template parameters of a class template, this is called "partial specialization". When doing this you create a new, specialized version of the template that "overrides" the general version.

In your case it seems that you only want to specialize a part of the template, the Foo() method, but this is not possible. You have to specialize the whole TC class:

// 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.
}
sth
A: 

If you wish only to specialize part of the class, you need the original class to provide hooks. It's generally describes as Traits or Policies depending on the implementation.

A Traits class is a class that references some properties, and sometimes methods, for a given type and is not passed explicitly. An example in the STL is std::iterator_traits<It>.

A Policy class is a class passed as a template parameter that is used to implement a number of functionality. An example in the STL is std::less<int> in std::set<int, std::less<int> >.

In general, the use of a Policy class is explicit while the use of a Traits is implicit... and thus I prefer the former to the latter.

If your class does not use these hooks, then report to sth answer on partial specialization and note that the partial means that some parameters are still template, and not that you only wish to specialize a part of the class, for indeed you have to redefine everything.

Matthieu M.
+1  A: 

For classes, yes. For functions, no and yes.

Partial template specialization is fine for classes, but for global functions it's a little more tricky.

For classes, you simply omit the specialized arguments from the template parameter list and include it in the class definition:

// 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] );

  }
};

For global functions, you can't do that. You can either define a function that is fully general, or fully specialized -- partial specialization of functions is disallowed.

However, you can partially specialize a function by creating it as a proxy for a static function of a partially specialized class.

e.g.

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

You can then specialize foo_impl in any way you want, and that will be reflected in foo.

Peter Alexander