O que é um template ?
A programação genérica no C++ se dá em grande parte através de templates. Eles parecem mágicos, pois diferente de um objeto, ele não verifica assinaturas.
https://gist.github.com/thiagomg/679eefc59beb8cf03d3b
Como saber se "C" tem o método sum, sem ter uma interface ?
Isso é validado em tempo de compilação, pois diferente de linguagens como Java, a função declarada com template existe somente quando é instanciada.
Vamos ver isso com exemplos e código rodando !
Tendo o arquivo abaixo
https://gist.github.com/thiagomg/53e521337e2bc2c32710
Vamos copilar e listar os símbolos
E temos o seguinte resultado:
O sumTemplated não aparece pois ele não existe! Apenas quando o template for instanciado ele vai aparecer, pois um template é compile-time programming.
Vamos verificar se isso está correto fazendo uma pequena modificação no nosso exemplo
https://gist.github.com/thiagomg/f640a1d878547b31655f
E o resultado agora é bem diferente
Ao fazer as chamadas usando int, double e float, o compilador criou uma versão de cada função para cada tipo, e assim, tendo versões concretas, elas aparecem na listagem de símbolos. Além disso, os tipos das funções template foram inferidos pelo compilador.
O funcionamento é o mesmo para classes com e sem templates, exceto pelo fato de que as classes que nunca são usadas também não aparecem na listagem de símbolos.
https://gist.github.com/thiagomg/c444563a5efd275df823
Temos aqui também uma versão para cada tipo gerado.
Ao final, mas não menos importante, como as funções e classes que usam templates somente existem quando são instanciadas em tempo de compilação, elas tendem a favorecer a geração de código inline, coisa muito importante para otimização!
Vamos ver um exemplo, pegando todos os códigos anteriores e compilando com otimização -O2
E o resultado
O único código gerado foi o sumNonTemplated, que é exportado por padrão. As funções com templates todas ficaram inline.
Eu pensei em falar em template instantiation neste post, mas isso é assunto para um post inteiro.
Até breve !
Código: https://github.com/SimplyCpp/examples/blob/master/temp_gen.cpp
A programação genérica no C++ se dá em grande parte através de templates. Eles parecem mágicos, pois diferente de um objeto, ele não verifica assinaturas.
https://gist.github.com/thiagomg/679eefc59beb8cf03d3b
Como saber se "C" tem o método sum, sem ter uma interface ?
Isso é validado em tempo de compilação, pois diferente de linguagens como Java, a função declarada com template existe somente quando é instanciada.
Vamos ver isso com exemplos e código rodando !
Tendo o arquivo abaixo
https://gist.github.com/thiagomg/53e521337e2bc2c32710
Vamos copilar e listar os símbolos
g++ -std=c++14 -c temp_gen.cpp && nm -C temp_gen.o
E temos o seguinte resultado:
0000000000000000 T sumNonTemplated(int, int)
0000000000000014 T run()
O sumTemplated não aparece pois ele não existe! Apenas quando o template for instanciado ele vai aparecer, pois um template é compile-time programming.
Vamos verificar se isso está correto fazendo uma pequena modificação no nosso exemplo
https://gist.github.com/thiagomg/f640a1d878547b31655f
E o resultado agora é bem diferente
W double sumTemplated<double>(double, double)
W float sumTemplated<float>(float, float)
W int sumTemplated<int>(int, int)
T sumNonTemplated(int, int)
T run()
Ao fazer as chamadas usando int, double e float, o compilador criou uma versão de cada função para cada tipo, e assim, tendo versões concretas, elas aparecem na listagem de símbolos. Além disso, os tipos das funções template foram inferidos pelo compilador.
O funcionamento é o mesmo para classes com e sem templates, exceto pelo fato de que as classes que nunca são usadas também não aparecem na listagem de símbolos.
https://gist.github.com/thiagomg/c444563a5efd275df823
W NonTemplated::sum(int)
W NonTemplated::NonTemplated(int)
W NonTemplated::NonTemplated(int)
n NonTemplated::NonTemplated(int)
W Templated<double>::sum(double)
W Templated<double>::Templated(double)
W Templated<double>::Templated(double)
n Templated<double>::Templated(double)
W Templated<int>::sum(int)
W Templated<int>::Templated(int)
W Templated<int>::Templated(int)
n Templated<int>::Templated(int)
Temos aqui também uma versão para cada tipo gerado.
Ao final, mas não menos importante, como as funções e classes que usam templates somente existem quando são instanciadas em tempo de compilação, elas tendem a favorecer a geração de código inline, coisa muito importante para otimização!
Vamos ver um exemplo, pegando todos os códigos anteriores e compilando com otimização -O2
g++ -O2 -std=c++14 -c temp_gen.cpp && nm -C temp_gen.o
E o resultado
T sumNonTemplated(int, int)
T run()
O único código gerado foi o sumNonTemplated, que é exportado por padrão. As funções com templates todas ficaram inline.
Eu pensei em falar em template instantiation neste post, mas isso é assunto para um post inteiro.
Até breve !
Código: https://github.com/SimplyCpp/examples/blob/master/temp_gen.cpp
Comentários
Postar um comentário