Si è possibile, l'argomento è noto come template specialization .
Fai conto di avere questo template di classe:

template <typename T>
class Stack{
...
};


Ad esempio lo puoi specializzare per le stringhe:

template<>
class Stack<std::string> {
...
};


Ovviamente poi ogni sua funzione deve riportare esplicitamente il tipo di dato che stai specializzando. Ad esempio...

std::string Stack<std::string>:op(){
...
}




La specializzazione può anche essere parziale. Ad esempio data
template <typename T1, typename T2>
class MyClass{
...
};


...sono possibili (ad es.) i seguenti tipi di specializzazione parziale:

//Entrambi i parametri sono dello stesso tipo
template <typename T>
class MyClass<T, T>{
};



//Il secondo parametro è un tipo (gia) noto
template <typename T>
class MyClass<T, int> {
};



//Entrambi i parametri sono puntatori, non necessariamente dello stesso tipo
template <typename T1, typename T2>
class MyClass<T1 *, T2 *>{
};



Dati poi i seguenti input...

MyClass<int, float>; //Invoca MyClass<T1, T2>
MyClass<float, float>; //Invoca MyClass<T, T>
MyClass<float, int>; //Invoca MyClass<T, int>
MyClass<int *, float *>; //Invoca MyClass<T1*, T2*>

Problemi possono sorgere qualora più specializzazioni parziali soddisfino allo stesso modo una chiamata. In questo caso la chiamata è ambigua e si riceve un errore.

MyClass<int, int>; //ERROR: invoca sia MyClass<T, T> che MyClass<T, int>
MyClass<int *,int *>; //ERROR: invoca sia MyClass<T,T> che MyClass<T1 *, T2 *>


La seconda può ad esempio essere risolta con un'altr specializzazione parziale.
template <typename T>
class MyClass<T *, T *>{
};