Как мне сделать эту явную специализацию? - PullRequest
6 голосов
/ 25 ноября 2010

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

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 ]

6 голосов
/ 25 ноября 2010

Для явной специализации doSomething необходимо также явно специализовать Test.

От 14.7.3 / 18:

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

2 голосов
/ 25 ноября 2010

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

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

template<> template<>
void Test<int>::doSomething<int>()
{
}
1 голос
/ 25 ноября 2010

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

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;
};
0 голосов
/ 25 ноября 2010

Не уверен, что это ошибка в 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>();
}
0 голосов
/ 25 ноября 2010

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, заключается в том, что нет проблем с компиляцией при специализации со встроенными определениями, но для специализаций с не встроенными определениями, если имеется более одной версии, компиляция не выполняется успешно.

0 голосов
/ 25 ноября 2010

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

...