Шаблонный метод специализации шаблона

Вот мой код:

template<typename T1, typename T2> class MyClass
{
public:
    template<int num> static int DoSomething();
};

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething()
{
    cout << "This is the common method" << endl;
    cout << "sizeof(T1) = " << sizeof(T1) << endl;
    cout << "sizeof(T2) = " << sizeof(T2) << endl;
    return num;
}

Это хорошо работает. Но когда я пытаюсь добавить этот

template<typename T1, typename T2> template<> int MyClass<T1, T2>::DoSomething<0>()
{
    cout << "This is ZERO!!!" << endl;
    cout << "sizeof(T1) = " << sizeof(T1) << endl;
    cout << "sizeof(T2) = " << sizeof(T2) << endl;
    return num;
}

Я получаю ошибки компилятора: недопустимая явная специализация перед токеном " > " template-id "DoSomething < 0 > " для "int MyClass:: DoSomething()" не соответствует объявлению шаблона

Я использую g++ 4.6.1 Что мне делать?

Ответ 1

К сожалению, вы не можете специализировать шаблон, являющийся членом шаблона класса, не специализируясь на внешнем шаблоне:

С++ 11 14.7.3/16: В явном объявлении специализации для члена шаблона класса или шаблона-члена, который появляется в области пространства имен, шаблон-член и некоторые из его вмещающих шаблонов классов могут оставаться неспециализированными, , за исключением того, что объявление не должно явно специализировать шаблон члена класса, если его встроенные шаблоны классов также явно не специализируются как.

Я думаю, что ваш лучший вариант - добавить дополнительный параметр в MyClass, а затем частично специализировать его.

Ответ 2

Это грустно, но верно: вы не можете явно специализировать шаблон класса, если его встроенные шаблоны классов также явно специализированы. Для получения дополнительной информации вы можете прочитать

Ниже я специализировался на MyClass, и все было сделано.

#include <iostream>
using namespace std;

template<typename T1, typename T2> class MyClass
{
public:
  template<int num> static int DoSomething();
};

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething()
{
  cout << "This is the common method" << endl;
  cout << "sizeof(T1) = " << sizeof(T1) << endl;
  cout << "sizeof(T2) = " << sizeof(T2) << endl;
  return num;
}

template<> template<> int MyClass<char, int>::DoSomething<0>()
{
  cout << "This is ZERO!!!" << endl;
  cout << "sizeof(T1) = " << sizeof(char) << endl;
  cout << "sizeof(T2) = " << sizeof(int) << endl;
  return 0;
}

int main() {
  MyClass<char, int> m;
  m.DoSomething<2>();
  m.DoSomething<0>();
  return 0;
}

Вывод:

This is the common method
sizeof(T1) = 1
sizeof(T2) = 4
This is ZERO!!!
sizeof(T1) = 1
sizeof(T2) = 4

EUREKA! Это хорошо работает на MSVCPP 10.

#include <iostream>
using namespace std;

template<typename T1, typename T2> class MyClass
{
public:
  template<int num> static int DoSomething();
  template<> static int DoSomething<0>() {
    cout << "This is ZERO!!!" << endl;
    cout << "sizeof(T1) = " << sizeof(T1) << endl;
    cout << "sizeof(T2) = " << sizeof(T2) << endl;
    return 0;
  }
};

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething()
{
  cout << "This is the common method" << endl;
  cout << "sizeof(T1) = " << sizeof(T1) << endl;
  cout << "sizeof(T2) = " << sizeof(T2) << endl;
  return num;
}

int main() {
  MyClass<char, int> m;
  m.DoSomething<2>();
  m.DoSomething<0>();
  return 0;
}

Вывод:

This is the common method
sizeof(T1) = 1
sizeof(T2) = 4
This is ZERO!!!
sizeof(T1) = 1
sizeof(T2) = 4

BTW, не return num; из специализации. Он никогда не знает, что такое num.