Как мне сделать эту явную специализацию?

Возможен ли следующий дизайн?:

template <typename T>
class Test{
 public:
  template <typename Z>
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};

Теперь, если бы это было возможно, я бы сделал несколько явных специализаций для doSomething, чтобы в конце у меня было несколько версий, как показано ниже:

void doSomething<int>(){
 //do something
}
void doSomething<double>(){
 //do something
}
...etc

что кажется невозможным, я не могу найти какой-либо синтаксис для выполнения этой работы, тогда я подумал, что, возможно, дизайн должен быть таким, как следует, чтобы все аргументы шаблона передавались самому классу шаблона:

template <typename T,typename Z>
class Test{
 public:
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};

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

template <typename T>
void Test<T,int>::doSomething(){
 //do something
}
template <typename T>
void Test<T,double>::doSomething(){
 //do something
}
...etc

Я получил следующие ошибки для явной специализации:
ошибка #1: список аргументов шаблона после имени шаблона класса должен перечислять параметры в порядке, используемом в списке параметров шаблона.
Ошибка № 2: "Контейнер1": слишком мало аргументов шаблона.

6 ответов

Решение

Для явной специализации doSomething Вы должны также явно специализироваться Test,

От 14.7.3/18:

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

Вы не можете явно специализовать шаблон элемента, если его шаблоны классов также не являются явно специализированными.

Так что будет работать только что-то подобное:

template<> template<>
void Test<int>::doSomething<int>()
{
}

Вы всегда можете сделать функцию встроенной

template <class T>
class Test
{
public:
 template <class Z>
 void doSomething() { cout << "default" << endl; }

 template<>
 void doSomething<int>() { cout << "int" << endl;}
 template<>
 void doSomething<double>() { cout << "double" << endl; }
private:
 T obj;
};

Я думаю, что этот привередлив. Я полагаю, вы не можете сделать это, прочитайте это.

Не уверен, что это ошибка в g++, но это компилирует и производит то, что я ожидаю.

#include<typeinfo>
#include<iostream>

template<typename T>
class Test
{
public:
    template<typename Z>
    void doSomething();

private:
    T obj;
};

template<typename T>
template<typename Z>
void Test<T>::doSomething()
{
    Z val;
    std::cout << __func__ << ": type " << typeid(val).name() << std::endl;
}

int main(int argc, char *argv[])
{
    Test<double> a;
    a.doSomething<int>();
    a.doSomething<double>();
}

icecrime опубликовал временный ответ, и он компилируется из-за некоторой ошибки, вероятно, в Visual C++ 2008:

template <typename T>
class Test{
 public:
  template <typename Z>
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};
template <>
template <typename T>
void Test<T>::doSomething<int>(){
 //do something
}

Проверьте его текущий ответ, хотя. Самое смешное, по крайней мере с VC++ 2008, состоит в том, что нет проблем с компиляцией при специализации со встроенными определениями, но для специализаций с не встроенными определениями, если имеется более одной версии, она не компилируется успешно.

Другие вопросы по тегам