quinta-feira, 30 de agosto de 2012

STL (Standard Template Library)


A STL é a biblioteca padrão de templates que descreve container, iteradores, algoritmos e functores de maneira genérica através de templates.

Um template de função são funções especiais que podem operar com tipos genéricos permitindo a criação de função template cuja funcionalidade pode ser adaptada para
mais de um tipo ou classe sem a repetição do código completo para cada tipo.

Um template de função é o corpo de uma função que definida pela palavra reservada template. Um template de função ainda não é uma função.

Uma função template é uma instância de um template de função que é gerada em tempo de execução tempo de compilação quando a função é chamada.

Um template de função pode ser definido da seguinte maneira:

template nome_da_funcao;
template nome_da_funcao;

Considere o seguinte exemplo:
/*
Autor: Wladimir Araújo Tavares
*/
#include iostream <
#include stdlib.h <
#include vector <

using namespace std;

template <typename T>
T GetMax(T a, T b){
      T result;
      if(a>b) result =a;
      else result = b;
      return result;
}

int main(){
            cout << GetMax(2,3) << endl; //int
            cout << GetMax(2.0f,3.0f) << endl; //float
            cout << GetMax(2L, 1L) << endl; //long int
            cout << GetMax(2u, 1u) << endl; //unsigned int
            cout << GetMax(2ul, 1ul) << endl; // unsigned long int
            cout << GetMax(2.0L,3.0L) << endl; //long double
            cout << GetMax(2,2L) << endl;
            system("PAUSE");
  return 0;
}
Observe que essa mesma função é instanciada 5 vezes, mas na última ocorre o seguinte  erro:
no matching function for call to `GetMax(int, long int)'

Se você quiser não gerar em tempo de execução a instancianção da função, você pode informa previamente ao compilador é o tipo da função template e utilizar todos os benefícios (malefícios) da tipificação fraca do C/C++ da seguinte maneira:

cout << GetMax (2,2L) << endl;

Você pode trabalhar com vetores e chamar o constructor do tipo da seguinte maneira:

template < typename T>
T sum_vector( vector  v  ){
     
      T result = T();
      typename vector::iterator it;
     
      for(it = v.begin(); it != v.end(); it++)
            result = result + (*it);
     
      return result;   
     
}

template < typename T>
T sum_array( T * array, int size ){
     
     
      T result = T(); // construtor do tipo T
      // T = int return 0
      // T = float return 0.0f
       
      for(int i=0;i
            result += array[i];
           
      return result;
     
}


int v1 [] = {2,3,4};
cout << sum_array ( v1, 3) << endl;
     
float v2 [] = {2.5,3.5,4.8};
cout << sum_array ( v2, 3) << endl;
     
vector <int> v3;
v3.push_back(2);
v3.push_back(3);
v3.push_back(4);
cout << sum_vector ( v3 ) << endl;
     
     
vector <double> v4;
v4.push_back(2.5);
v4.push_back(3.5);
v4.push_back(4.8);
     
cout << sum_vector ( v4 ) << endl;

Classe Template Pair

template <class T1, class T2> struct pair
{
  typedef T1 first_type;
  typedef T2 second_type;

  T1 first;
  T2 second;
  pair() : first(T1()), second(T2()) {}
    pair(const T1& x, const T2& y) : first(x), second(y) {}
  template <class U, class V>
    pair (const pair &p) : first(p.first), second(p.second) { }
}


Construtor 1: pair() : first(T1()), second(T2()) {}
pair p1;

Construtor 2: pair(const T1& x, const T2& y) : first(x), second(y) {}
pair p2(2,3);

Construtor 3: (const pair &p) : first(p.first), second(p.second) { }  
pair p3(p1);

cout << p1.first << " " << p1.second << endl;
cout << p2.first << " " << p2.second << endl;
cout << p3.first << " " << p3.second << endl;

Saída
0 0
2 3
0 0

Um template de classe também pode ter parâmetros que devem ser inicializados.

const int OnFullArray = 1;
const int OufOfRange  = 2;
const int NotFoundElem = 4;

template <class T, int SIZE>
class Array{
     
      private:
            T array[SIZE];
            int size;
           
      public:
     
      Array() : size(0) {}
     
      bool full(){ return size==SIZE; }
     
      void push(T elem){
 
      const int OnFullArray = 1;
const int OufOfRange  = 2;
const int NotFoundElem = 4;

template <class T, int SIZE>
class Array{
     
private:
      T array[SIZE];
      int size;
           
public:
     
Array() : size(0) {}
     
      bool full(){ return size==SIZE; }
     
      void push(T elem){
 
            if(!full() ){
                  array[size++] = elem;
            }else{
                  throw OnFullArray;
            }
 
      }

      T get(int pos){
            if( pos >= SIZE || pos < 0) throw OufOfRange;
            if( pos >= size ) throw NotFoundElem;
            return array[pos];
      }

      void print(){
            for(int i=0;i
                  cout << array[i] << endl;

      }
     
};



Array <int, 3> v;
v.push(2);
v.push(3);
v.push(4);
try{
  v.push(5);
}catch(int e){
  if(e==OnFullArray){
   cout << "Vetor esta cheio\n";
  }
 }
v.print();




Um comentário:

Anônimo disse...

"Uma função template é uma instância de um template de função que é gerada em tempo de execução."

Não seria em tempo de compilação?