logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

Tutorial de STL, parte 1/2: Mais templates

No primeiro post da série vimos qual a função básica dos templates: transformar os tipos de dados em parâmetros, assim como já são os valores. Isso permite que você faça uma função - na realidade um template de função - que consiga tratar vários tipos de dados e continuar tipada. Essa é a base do "generic programming", separar o algoritmo do tipo de dado. Dessa forma, qualquer tipo de dado que tenha suporte aos requisitos exigidos para o funcionamento do algoritmo pode ser usado. Esses requisitos em relação a um tipo de dado tem o nome de "concept", e será nativamente suportado pela linguagem no C++0x. Veremos mais sobre isso em breve.

No nosso primeiro exemplo resolvemos o problema de duplicação do código da função, mas não resolvemos o problema do código que chama a função, pois só trocamos a sintaxe soma_int para sintaxe soma<int>. O que eu não contei na primeira parte é que o compilador C++ faz a resolução automática de tipos para os parâmetros, sempre que possível. Nosso código pode ser modificado para:

template <typename T>
T soma(T x, T y)
{
  return x + y;
}

int main()
{
  soma(2,2);
  soma(2.99f, 2.99f);
  soma(5.9999, 6.9999);
  soma('2', '2'); // não, o resultado não será '4'...

  return 0;
}

Nesse caso específico, o compilador consegue saber com certeza qual o tipo de dado envolvido nas chamadas. Dessa forma podemos deixar o trabalho por conta dele. Mas existem alguns casos que não são claros:

  int i = 10;
  float f = 10.2;

  double d = soma(i,f);

------ Build started: Project: 1bit_stl, Configuration: Debug Win32 ------

Compiling...
1bit_stl.cpp
1bit_stl.cpp(115) : error C2782: 'T soma(T,T)' : template parameter 'T' is ambiguous
        1bit_stl.cpp(96) : see declaration of 'soma'
        could be 'float'
        or       'int'

Oops. Sabemos que o compilador poderia ser bonzinho e promover os dois parâmetros para double, fazer a conta, e retornar o resultado. Sim, mas lembre-se da filosofia C++: você só paga por aquilo que você pedir. Nos primeiros casos o compilador fez a dedução porque era absolutamente óbvio, nesse caso não é. Conversões implícitas podem ser uma praga a te perseguir, e o compilador C++ te livra disso exigindo que você diga exatamente o que você quer.

Outra coisa que podemos notar nesse exemplo: não existe sobrecarga de retorno de função. O fato de colocarmos o retorno da função em uma variável double não mudou em nada o comportamento da resolução de tipo. Em C++ você não pode fazer sobrecarga de função mudando somente o tipo de retorno. E esse nosso template nada mais é do que uma função vitaminada, as regras continuam valendo. Como nesse caso precisamos ser explícitos, vale a sintaxe normal:

  int i = 10;
  float f = 10.2;

  double d = soma<double>(i,f);

Dessa forma o compilador faz a promoção automática dos tipos int e float para double, o que não nos causa nenhum problema de perda de dados.

No começo do post eu falei sobre abstrair o algoritmo do tipo de dados, e é o que fizemos com nossa função soma. O conceito é simples: independente do tipo do dado, os passos necessários para se fazer uma soma são os mesmos. O que muda é a forma como a soma que é feita, que é uma característica intrínseca do tipo. Esse mesmo conceito se aplica para algoritmos mais complicados, como os de ordenação. Eles comparam os valores entre si, e a comparação de valores é diferente para cada tipo de dado. Mesmo assim, o algoritmo de ordenação continua o mesmo.

Um exemplo clássico que vou usar para ilustrar isso é uma classe para representar um número complexo. Um número complexo é representado com ai + b, sendo a e b dois números reais, e i a parte imaginária (sendo i ao quadrado igual a -1 e tendo seus detalhes explicados na Wikipedia como de costume). As operações de soma e subtração de um número complexo são feitas da seguinte forma:

Esses algoritmos acima não se encaixam com o nosso template de soma:

  complex_number c1  = {10, 20}, c2  = {40, 30};
  soma<complex_number>(c1, c2);

------ Build started: Project: 1bit_stl, Configuration: Debug Win32 ------

Compiling...
1bit_stl.cpp
1bit_stl.cpp(98) : error C2676: binary '+' : 'complex_number' does not define this operator 
  or a conversion to a type acceptable to the predefined operator
        1bit_stl.cpp(128) : see reference to function template 
  instantiation 'T soma(T,T)' being compiled
        with
        [
            T=complex_number
        ]

Build Time 0:00
1bit_stl - 1 error(s), 0 warning(s)

---------------------- Done ----------------------

    Build: 0 succeeded, 1 failed, 0 skipped

Note que os passos para nosso complicadíssimo algoritmo ainda são os mesmos - passo único: efetuar a operação de soma - o que muda é forma como a soma é efetuada. Para ficar mais claro, imagine uma equação quadrada:

Nesse caso a soma é só um passo do algortimo para se chegar ao resultado. A forma como a soma é feita é diferente para números inteiros (int) ou reais (double), mas a ordem dessa soma dentro dos passos do algoritmo ainda é a mesma.

Voltando ao nosso super algoritmo de soma, precisamos de um tratamento diferenciado para somar números complexos. Veremos as várias formas de resolver isso no próximo post.


Em 30/05/2006 16:06, por Rodrigo Strauss


  
 
 
Comentários
Angel Portal | website | em 18/07/2006 | #
Gostaria de saber se tem este tutorial para download em algum
lugar?
Tambem gostaria de saber se ver com os compiladores normais como o Borland C++ ou se tenho que instalar no meu ambiente?

Angel Portal
Rodrigo Strauss | website | em 18/07/2006 | #
Como assim download? Esse é o tutorial.

Não entendi sua pergunta sobre o Borland C++
diego | e-mail | em 04/06/2007 | #
cara este artigo teu me ajudou de mais
valeu
Midori | website | e-mail | em 13/08/2008 | #
uhuu
to começando a estudar C++ o/
Rodrigo Strauss | website | em 15/08/2008 | #
:-)
Insaulo | em 18/07/2011 | #
Pô cara, muito bom o blog, mas cadê as atulizações?! Você abandonou o site, parecia um bom lugar pra aprender c++...
Algo a dizer?
Nome:


Site:


E-mail:


Escreva o número vinte e seis:


 Não mostre meu e-mail no site, não serve pra nada mesmo...

Comentário





Os comentários devem ser sobre assuntos relativos ao post, eu provavelmente apagarei comentários totalmente offtopic. Se quiser me enviar uma mensagem, use o formulário de contato. E não esqueça: isso é um site pessoal e eu me reservo o direito de apagar qualquer comentário ofensivo ou inapropriado.
rebarba rebarba
  ::::