Como escrever a definição de uma template interna a uma classe template fora dessa classe
Adiando a definição de uma template interna a uma classe template
Às vezes devido às dependências do código precisamos adiar a definição de uma template até um determinado ponto do programa fonte – por exemplo se no código dessa template for necessário uma declaração feita mais a frente. Outro motivo seria simplesmente manter a declaração da classe pequena, deixando a definição em outra parte do código – sem contar que qualquer declaração dentro de uma classe será automaticamente considerada inline sempre que possível.
A sintaxe para isto é estranha. Veja os trechos de código a seguir.
Declaração:
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
template <class T>
class Estado {
private:
string nome;
T t;
public:
Estado( string nome );
template <class U> class Municipio {
private:
string nome;
public:
Municipio( string nome );
int praias();
template <class V> void hotel( V v );
};
template <class W> void cobertura( W w );
};
A classe Estado é uma template com um construtor e um método template (cobertura), e a classe Municipio é uma template interna à classe Estado, e possui um método comum (praias) e um outro método template (hotel). O método hotel depende de três parâmetros template: T, U e V.
Não há mistério na definição fora da classe do construtor Estado. A coisa começa a ficar estranha para o método cobertura, pois este precisa de dois parâmetros.
template <class T>
Estado<T>::Estado( string nome ): nome(nome), t(0) {
// Um código qualquer aqui
}
template <class T, class W>
void Estado<T>::cobertura( W w ) {
t = w;
// Um código qualquer aqui
}
A saída para esta compilação é:
38 main.cpp: prototype for `void Estado<T>::cobertura(W)' does not match any in class `Estado<T>' 38 main.cpp: template<class T> template<class W> void Estado::cobertura(W) 38 main.cpp: template definition of non-template `void Estado<T>::cobertura(W)' [Build Error] [main.o] Error 1
A linha 2 já nos indica qual a solução: template <class T> template<class W>
A sintaxe para a declaração de templates aninhadas é essa. Com qualquer nível de aninhamento. Assim, o código final para a declaração das templates externamente à classe é mostrado a seguir.
Código final:
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
template <class T>
class Estado {
private:
string nome;
T t;
public:
Estado( string nome );
template <class U> class Municipio {
private:
string nome;
public:
Municipio( string nome );
int praias();
template <class V> void hotel( V v );
};
template <class W> void cobertura( W w );
};
template <class T>
Estado<T>::Estado( string nome ): nome(nome), t(0) {
// Um código qualquer aqui
}
template <class T> template <class W>
void Estado<T>::cobertura( W w ) {
t = w;
// Um código qualquer aqui
}
template <class T> template <class U>
Estado<T>::Municipio<U>::Municipio( string nome ): nome(nome) {
// Um código qualquer aqui
}
template <class T> template <class U>
int Estado<T>::Municipio<U>::praias() {
// Um código qualquer aqui
return 0;
}
template <class T> template <class U> template <class V>
inline void Estado<T>::Municipio<U>::hotel( V v ) {
// Um código qualquer aqui
}
int main(int argc, char *argv[])
{
Estado<int> rio("Rio de Janeiro");
Estado<int>::Municipio<double> buzios("Búzios");
rio.cobertura( 4 );
buzios.hotel( 5 );
cout << buzios.praias() << endl;
return EXIT_SUCCESS;
}
Dessa forma, além de podermos contornar as possíveis dependências do código também podemos manter a declaração de uma classe template enxuta – sem comprometer o desempenho, pois nada impede que usemos a opção inline (linha 55).
“All the world’s a stage…”