Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template specialization with a templatized type

I want to specialize a class template with the following function:

template <typename T>
class Foo
{
public:
    static int bar();
};

The function has no arguments and shall return a result based on the type of Foo. (In this toy example, we return the number of bytes of the type, but in the actual application we want to return some meta-data object.) The specialization works for fully specified types:

// specialization 1: works
template <>
int Foo<int>::bar() { return 4; }

// specialization 2: works
template <>
int Foo<double>::bar() { return 8; }

// specialization 3: works
typedef pair<int, int> IntPair;
template <>
int Foo<IntPair>::bar() { return 2 * Foo<int>::bar(); }

However, I would like to generalize this to types that depend on (other) template parameters themselves. Adding the following specialization gives a compile-time error (VS2005):

// specialization 4: ERROR!
template <>
template <typename U, typename V>
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); }

I am assuming this is not legal C++, but why? And is there a way to implement this type of pattern elegantly?

like image 317
kmhofmann Avatar asked Feb 04 '23 08:02

kmhofmann


2 Answers

Partitial specialization is valid only for classes, not functions.

Workaround:

template <typename U, typename V>
class Foo<std::pair<U, V> > { 
public:
 static int bar() { return Foo<U>::bar() + Foo<V>::bar(); }
};

If you does not want to specialize class fully, use auxiliary struct

template<class T>
struct aux {
  static int bar();
};

template <>int aux <int>::bar() { return 4; }
template <>int aux <double>::bar() { return 8; }

template <typename U, typename V>
struct aux <std::pair<U, V> > { 
  static int bar() { return Foo<U>::bar() + Foo<V>::bar(); }
};

template<class T>
class Foo : aux<T> {
  // ... 
};
like image 139
Alexey Malistov Avatar answered Feb 06 '23 16:02

Alexey Malistov


It is perfectly legal in C++, it's Partial Template Specialization.
Remove the template <> and if it doesn't already exists add the explicit class template specialization and it should compile on VS2005 (but not in VC6)

// explicit class template specialization
template <typename U, typename V>
class Foo<std::pair<U, V> >
{
public:
    static int bar();
};

template <typename U, typename V>
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); }
like image 29
TimW Avatar answered Feb 06 '23 16:02

TimW