martes, 4 de octubre de 2016

Que es template en c++?


Template es como generic de java. En resumen.

Pero voy a explayarme un poco más pero solo un poco con un ejemplo. Supongamos que tenemos que hacer una lista de enteros, lo hacemos y listo. Pero inmediatamente necesitamos una lista de string y lo hacemos. Pero inmediatamente necesitamos una lista de double y creo que se va entendiendo la idea.

En los lenguajes de tipado estáticos, tenemos ese problema, por cada tipo debemos hacer una estructura de ese tipo particular. Y de este problema nace un concepto que se lo llama programación genérica. Es decir, la programación genérica nos permite programar estructuras sin definir un tipo determinado y esto nos permite generalizar.

Esto ayuda muchísimo a la reutilización y en c++ tenemos una librería estandar que nos provee estructuras genéricas. Pilas, colas, mapas, etc.

Veamos un ejemplo de un árbol b :

arbol.h
#ifndef ARBOL_H
#define ARBOL_H

template <class T>
//con template digo que mi clase va a ser una plantilla

class Arbol
{
private:
    Arbol<T> * izq = 0;
    Arbol<T> * der = 0;
    T dato;
public:
    Arbol(T dato);
    void agregar(T otroDato);
    void listarEnOrden();
};

#endif // ARBOL_H

arbol.cpp
#include "arbol.h"
#include <iostream>

using namespace std;

template <class T>
Arbol<T>::Arbol(T dato)
{
    this->dato = dato;
}

template <class T>
void Arbol<T>::agregar(T otroDato){
    if (this->dato > otroDato) {
        if (this->izq != 0) {
            this->izq->agregar(otroDato);
        } else {
            this->izq = new Arbol(otroDato);
        }
    } else {
        if (this->der != 0) {
            this->der->agregar(otroDato);
        } else {
            this->der = new Arbol(otroDato);
        }
    }
}

template <class T>
void Arbol<T>::listarEnOrden() {
    if (this->izq != 0) {
        this->izq->listarEnOrden();
    }
    cout << this->dato << "  ";
    if (this->der != 0) {
        this->der->listarEnOrden();
    }
}

Veamos como usar este árbol: 

#include <iostream>
#include "arbol.cpp"
using namespace std;

int main()
    Arbol<int> arbolEntero(5); // Como vemos le tengo que indicar el tipo donde estaba T
    arbolEntero.agregar(3);
    arbolEntero.agregar(2);
    arbolEntero.agregar(6);
    arbolEntero.agregar(7);
    arbolEntero.listarEnOrden();
    return 0;
}


Otro ejemplo un map: 
map.h
#ifndef MAP_H
#define MAP_H

template <class K, class V>

class Map
{
private:
    int count = 0;
    K * keys;
    V * values;
public:
    Map();
    void put(K key, V value);
    V get(K key);
};

#endif // MAP_H

map.cpp:
#include "map.h"

template <class K, class V>
Map<K,V>::Map()
{
    this->count = 0;
}

template <class K, class V>
void Map<K,V>::put(K key, V value){
    K * auxKey = new K (count + 1);
    K * auxValue = new V (count + 1);
    for(int i = 0; i < count; i++){
        auxKey[i]= this->keys[i];
        auxValue[i] = this->values[i];
    }
    auxKey[count] = key;
    auxValue[count] = value;

    if (this->count > 0) {
        delete this->keys;
        delete this->values;
    }

    count++;

    this->keys = auxKey;
    this->values = auxValue;
}

template <class K, class V>
V Map<K,V>::get(K key){
    int index = 0;
    for(int i = 0; i < count; i++){
        if (key == this->keys[i]) {
            index = i;
        }
    }
    return this->values[index];
}

Veamos como usar el map: 

#include <iostream>
#include "map.cpp"

using namespace std;

int main()
{
    Map<int,int> myMap = Map<int,int>();
    myMap.put(1,2);
    myMap.put(2,3);
    myMap.put(4,5);
    cout<< myMap.get(1) << " "<<myMap.get(2) << " "<< myMap.get(4);
    return 0;
}