Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial template specialization outside class definition

Tags:

c++

templates

I can use partial template specialization inside class declaration

template<class T1, class T2>
struct A
{
    void foo() { cout << "general"; }
};

template<class T1>
struct A<T1, int>
{
    void foo() { cout << "partial specialization"; }
};

But when I'm trying to do it outside class declaration

template<class T1, class T2>
struct A
{
    void foo();
};


template<class T1, class T2>
void A<T1, T2>::foo() { cout << "general"; }

template<class T1>
void A<T1, int>::foo() { cout << "partial specialization"; }

I get the following error:

invalid use of incomplete type «struct A < T1, int >»

It's not a problem to use the first approach when you want to redefine all members, but what if you want redefine only one method without code duplication for all others?

So, is it possible to use partial template specialization outside class definition?

like image 491
Nelson Tatius Avatar asked Oct 13 '12 17:10

Nelson Tatius


2 Answers

It's not a problem to use the first approach when you want to redefine all members, but what if you want redefine only one method without code duplication for all others?

This is where traits technique can be used. See http://www.boost.org/community/generic_programming.html#traits

Some usage:

template <class T1, class T2>
struct ATraits {
   static void foo() {}
};

template <class T1>
struct ATraits<T1,int> {
   static void foo() {}
};

template <class T1, class T2>
struct A {
   void foo() { ATraits<T1,T2>::foo(); }
};
like image 139
PiotrNycz Avatar answered Oct 05 '22 13:10

PiotrNycz


In your failing example:

template<class T1>
void A<T1, int>::foo() { cout << "partial specialization"; }

You are referring to a specialization of A which you haven't defined yet (you have only defined the full template in the second example).

If you add the specialization before you refer to it, it should indeed work:

template <class T1>
struct A<T1, int>
{
  void foo ();
};

template <class T1>
void A<T1, int>::foo ()
{
  /* something */
};
like image 41
mauve Avatar answered Oct 05 '22 13:10

mauve