Dean
Dean

Reputation: 6958

Template partial specialization won't work

I don't understand why the following fails:

#include <cassert>
#include <memory>
#include <utility>

using namespace std;

template<typename... T> struct name{ static const char* value; };

template<typename... T> const char* name<T...>::value = "unknown";
template <> const char* name<int>::value = "int";
template <> const char* name<float>::value = "float";
template <> const char* name<template<typename,typename> class T>::value = "pair";

int main()
{
    assert(name<int>::value == "int");
    assert(name<float>::value == "float");
    assert(name<double>::value == "unknown");
    assert((name<pair<int, char> >::value) == "pair");
}

the problem is in the line

template <> const char* name<template<typename,typename> class T>::value = "pair";

[temp.class.spec.mfunc] should define this behavior but after reading the standard I still don't understand it. Can someone explain me (in the most clear and concise way possible) why none of these work?

template <> const char* name<template<typename,typename> class T>::value = "pair";
template <typename T1, typename T2> const char* name<std::pair<T1,T2>>::value = "pair";

Upvotes: 1

Views: 60

Answers (1)

You can partially specialise a class template, but you cannot partially specialise a member of a class template. And that's precisely what you're trying to do with the pair thing.

Why preceisely the attempts don't work:

template <> const char* name<template<typename,typename> class T>::value = "pair";

An explicit specialisation (that is, not a partial specialisation) is not a template. It is prefixed by template <>, and the fully specialised template name has to have arguments specified for all template parameters. So you could do for example this:

template <> const char* name<std::pair<int, double>>::value = "pair";

But your original code is syntactic nonsense - if anything, it looks like trying to declare a two-parameter class template T inside the template argument list.

As to the second line:

template <typename T1, typename T2> const char* name<std::pair<T1,T2>>::value = "pair";

This is correct syntax for partial specialisation. Unfortunately, as I said above, you cannot partially specialise class template members, only entire class templates. So you have to do this:

template <typename T1, typename T2> struct name<std::pair<T1,T2>>
{
  static const char* value;
};

template <typename T1, typename T2> const char* name<std::pair<T1,T2>>::value = "pair";

Upvotes: 1

Related Questions