Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ partial method specialization

Is there a partial specialization for template class method?

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

it doesn't work to specialize it like this:

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

Any help?

like image 776
faya Avatar asked Oct 08 '09 05:10

faya


2 Answers

If you are already have specialized class you could give different implementation of foo in specialized class:

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

To specialize member function in Visual C++ 2008 you could make it template too:

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

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

The solution above seems to will be available only in future C++ Standard (according to draft n2914 14.6.5.3/2).

like image 63
Kirill V. Lyadvinsky Avatar answered Oct 27 '22 06:10

Kirill V. Lyadvinsky


I think there is a misunderstanding there.

There are two kinds of templates:

  • the template classes
  • the template methods

In your example, you have a template class, which of course contains some methods. In this case, you will have to specialize the class.

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

The problem in your example is relatively simple: you define the method foo for the specialization C but this specialization has never been declared beforehand.

The problem here is that you have to fully specialize your C class (and thus copying a lot of data). There are a number of workarounds.

  • Inheritance (Composition ?): do all the common work in a base class, then have the C class inherits and specialize as appropriate
  • Friend: instead of having the 'foo' method being a member of C, define it as a friend free functions and specialize only this method
  • Delegation: have your 'foo' method call another method 'bar', which is a free function, and specialize 'bar' appropriately

Which in code gives:

// 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()); }
};

Hope it clarifies, and helps!

like image 24
Matthieu M. Avatar answered Oct 27 '22 08:10

Matthieu M.