Pergunta

O seguinte design é possível?:

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

Agora se fosse possível eu faria algumas especializações explícitas para doSomething para que no final tivesse algumas versões como abaixo:

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

o que parece impossível, não consigo encontrar nenhuma sintaxe para fazer o trabalho, então pensei que talvez o design devesse ser o seguinte, para que todos os argumentos do modelo fossem passados ​​​​para a própria classe do modelo:

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

Então tentei a especialização parcial que nem compilou:

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

Recebi os seguintes erros para especialização explícita:
erro#1: a lista de argumentos do modelo após o nome do modelo de classe deve listar os parâmetros na ordem usada na lista de parâmetros do modelo.
erro#2:'Container1': poucos argumentos de modelo.

Foi útil?

Solução

Para se especializar explicitamente doSomething você também precisa se especializar explicitamente Test.

A partir de 14.7.3/18:

Em uma especialização explícita Declaração para um membro de uma classe ou um modelo de membro que aparece no escopo do namespace, o membro modelo e alguns de seus anexos Os modelos de classe podem permanecer não especializado, exceto que o declaração não deve explicitamente especializar um modelo de membro da classe se seus modelos de classe de inclusão não são explicitamente especializada também.

Outras dicas

Você não pode especializar explicitamente um modelo de membro, a menos que seus modelos de classe envolventes também sejam explicitamente especializados.

Então, apenas algo assim funcionará:

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

você sempre pode tornar a função inline

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

Eu acho que este é exigente.Suponho que você não consiga fazer isso, leia esse.

Não tenho certeza se isso é um bug no g++, mas compila e produz o que espero.

#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 postou uma resposta temporária e foi compilada devido a algum bug provavelmente no 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
}

Verifique sua resposta atual.O engraçado, pelo menos com o VC++ 2008, é que não há problema em compilar ao se especializar com definições inline, mas para especializações com definições não inline, uma vez que há mais de uma versão, ela não é compilada com sucesso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top