Шаблонный метод специализации шаблонного класса - PullRequest
10 голосов
/ 14 февраля 2012

Вот мой код:

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

, я получаю ошибки компилятора: недопустимая явная специализация перед «>» идентификатором шаблона токена «DoSomething <0>» для «int MyClass :: DoSomething ()» несоответствовать любому объявлению шаблона

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

Ответы [ 3 ]

8 голосов
/ 14 февраля 2012

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

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

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

0 голосов
/ 05 мая 2018

Старый вопрос, я знаю,

но я наткнулся на ту же проблему в моем текущем проекте и нашел обходной путь, который выполняет работу, по крайней мере, для аргументов шаблона, которые не являются типами, кроме значений (например, template <int num>).

Реализация моего решения:

template<class T> template<int num> void Classname<T>::methodname()
{
    if (num == 0)
    {
        //implementation for num == 0
    }
    else if (num == 1)
    {
        //implementation for num == 1
    }
    //more cases...
}

num == constant будет вычислять константное выражение, поэтому компилятор оптимизирует ваш код, чтобы просто сохранить правильную реализацию для каждого случая.

Пожалуйста, поправьте меня, если я ошибаюсь или если что-то делает это плохим решением;)

0 голосов
/ 14 февраля 2012

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

Ниже я сначала специализировал 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

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

...