A Coder’s Corner

Blog de tecnologia y programación

Templates de C++ – Una Introducción

Posted by gfaraj on May 1, 2007

Los templates son muy importantes en el desarrollo de software con C++. Es sin duda una de las caracteristicas mas importantes (si no es la mas importante) de este lenguaje. Nos permite escribir codigo generico que puede ser usado con varios tipos de datos. Sin templates, se tendrian que reescribir muchas funciones y clases. Tomemos el siguiente ejemplo de una funcion que retorna el maximo de dos valores.

int max(int x, int y)
{
    return (x < y) ? y : x;
}

float max(float x, float y)
{
    return (x < y) ? y : x;
}

Como podemos ver, sin templates dos funciones que tienen el mismo cuerpo se tienen que reescribir para que funcione con varios tipos. Veamos la misma funcion usando templates.

template <typename T>
T max(T x, T y)
{
    return (x < y) ? y : x;
}

Esta funcion funciona con cualquier tipo que se pueda comparar con el operador <. Funciona hasta con tu propia clase si ella tiene el operador < implementado. Tambien se puede tener templates para clases. Clases como std::vector y std::list son templates y nos permiten usarlas para cualquier tipo que querramos. Veamos un ejemplo de una clase template.

template <typename T>
class Puntero
{
    T* _ptr;

public:
    explicit Puntero(T* ptr = 0) : _ptr(ptr) {}
    ~Puntero() { delete _ptr; }

    // implementamos estos operadores para que la clase actue como puntero
    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
};

int main()
{
    Puntero<int> puntero_int(new int);
    *puntero_int = 10;

    Puntero<bool> puntero_bool(new bool);
    *puntero_bool = true;
}

Ahi podemos ver una clase (incompleta) que trata de personificar un puntero. Cuando se destruye una instancia de esta clase, tambien destruye el puntero que contenia. Ahi pueden ver lo facil que es hacer una clase generica y los beneficios que esto trae. Sin templates, hubiera tenido que copiar la misma clase dos veces, cambiando ‘int’ por ‘bool’ solamente. Ahi se va notando que el reuso del codigo puede ser significativo al usar templates. Imaginense reimplementar std::vector por cada tipo que se quiera usar…

Bueno, esta solo era una pequeña introduccion. Espero que les haya gustado y volvere con algo mas avanzado la proxima. ;)

15 Responses to “Templates de C++ – Una Introducción”

  1. wow que bien por fin tengo un poco de idea sobre templates :) es que esta es la primera informacion que leo en espanol, todo el tiempo lo veia en ingles, y no sabia como seria la traduccion a espanol, pero veo que no se lo traduce xD

    gracias por el articulo :)

  2. gfaraj said

    Me alegra que te haya gustado :)

    La traduccion de la palabra “template” a español seria “plantilla”, pero prefiero mantener la palabra “template” porque asi se muestra en el codigo.

  3. Alexi said

    Hola,

    Quisiera hacer una consulta..

    ¿Como puedes usar los template para paginas web? o como uso C++ para los sitios web

    Gracias

  4. gfaraj said

    Estos templates no tienen nada que ver con los templates de una pagina web (como por ejemplo Smarty para PHP). C++ se puede usar por medio de CGI en un servidor web. Tambien se puede usar para crear controles ActiveX para Internet Explorer. Espero haber respondido tu pregunta.

  5. Dulcinea said

    Genial!!!!…creo que es la explicación mas clara y sencilla que puede haber sobre los templates… buena anotación la de que vale para clases si tienes implementado el operador ;) .

    Enhorabuena!!!…

  6. gfaraj said

    Gracias Dulcinea. Me alegra que te halla gustado :)

  7. Parmaia said

    Buenas, estoy trabajando con templates y al definir mi clase en un .h y la implementacion en un .cpp tengo un error al momento del enlace como si el compilador no consiguiera la implementacion que esta en el .cpp, si lo hago todo en el mismo .h funciona perfecto, cual puede ser la causa?

    Ejemplo:

    MiClase.h

    #ifndef MiClase_H
    #define MiClase_H

    template
    class MiClase{
    public:
    MiClase();
    void Algo(Tipo A);
    };

    #endif

    MiClase.cpp

    #include "MiClase.h"

    template
    MiClase::MiClase(){
    //Nada...
    }

    template
    void MiClase::Algo(Tipo A){
    //Nada...
    }

    main.cpp

    #include "MiClase.h"

    int main(){
    MiClase C;
    C.Algo(5);
    return 0;
    }

    Para compilar:
    g++ MiClase.cpp main.cpp -o Ejecutable

    Error:
    /tmp/cc6XNSRb.o: In function `main’:
    main.cpp:(.text+0×194): undefined reference to `MiClase::MiClase()’
    main.cpp:(.text+0×1a7): undefined reference to `MiClase::Algo(int)’
    collect2: ld devolvió el estado de salida 1

    Gracias de antemano por cualquier comentario al respecto.

  8. Parmaia said

    Perdon, no salieron los < > escribo el ejemplo de nuevo:

    MiClase.h

    #ifndef MiClase_H
    #define MiClase_H

    template <class Tipo>
    class MiClase{
    public:
    MiClase();
    void Algo(Tipo A);
    };

    #endif

    MiClase.cpp

    #include "MiClase.h"

    template <class Tipo>
    MiClase<Tipo>::MiClase(){
    //Nada...
    }

    template <class Tipo>
    void MiClase<Tipo>::Algo(Tipo A){
    //Nada...
    }

    main.cpp

    #include "MiClase.h"

    int main(){
    MiClase<int> C;
    C.Algo(5);
    return 0;
    }

    Para compilar:
    g++ MiClase.cpp main.cpp -o Ejecutable

    Error:
    /tmp/cc6XNSRb.o: In function `main’:
    main.cpp:(.text+0×194): undefined reference to `MiClase<int>::MiClase()’
    main.cpp:(.text+0×1a7): undefined reference to `MiClase<int>::Algo(int)’
    collect2: ld devolvió el estado de salida 1

    Gracias de antemano por cualquier comentario al respecto.

  9. gfaraj said

    @Parmaia:

    Las definiciones de los templates requieren estar disponibles al momento de compilarse. Por esta razon, lo ideal es poner todo en el header (.h). Existe lo que se llama “explicit instantiation,” que permite instanciar un template para un grupo de tipos en especifico (por ejemplo, MiClase<int> y MiClase<float>). Esto permite poner las definiciones en un .cpp, pero otros archivos solo podran usar el template con los tipos especificos con los que fue instanciado explicitamente.

    template class MiClase<int>;
    template class MiClase<float>;

    Otra opcion, es el keyword “export.” El problema aqui es que muy pocos compiladores han implementado esto y la verdad que al final no es muy util. Lo mas practico es definir todo en el .h.

  10. JHAx86 said

    Gracias, en la Wiki de OGRE te mandan a comprar un libro si no sabes lo que son templates. Pero gracias a ti no tengo que perder más tiempo, cosas como éstas enriquecen la web.

    Saludos.

  11. yo said

    Tengo algunas dudas existenciales, no sé si este es el mejor sitio

    Un asterisco delante de una variable es un puntero, hasta aqui ok:

    *puntero_int

    pero detras de un tipo o una variable que es?

    T* operator

    Un ampersand delante de una variable, es un paso por referencia:

    &var_name

    pero detras de un tipo que es?

    T& operator*

    Muchas gracias

  12. leon said

    Eh creo que ya no vas a volver a leer esto, pero por si alguien mas pasa y tiene dudas parecidas no da para dejarlas asi sin contestar =)

    *puntero_int
    no es un puntero, el puntero es “puntero_int” (una variable de tipo puntero). El * delante de una variable se pude leer como “valor apuntado por”. Te queda “valor apuntado por puntero_int”.

    T* puntero
    Eso define un puntero a algo de tipo T. El * despues de un nombre de tipo es como decir “puntero a”. T* se lee como “puntero a T” y es un tipo de variable.

    &var_name
    El & delante de un nombre de variable NO es una referencia, es la direccion de memoria del contenido de var_name. Por decirlo sin mucha “correctancia”, te devuelve un puntero a la variable. Se podria leer como “puntero a”. Te queda “puntero a var_name” (lo mas correcto es leerlo como “direccion de”). Creo que & usado asi se llama “operador de indireccion”, pero no me juego a ello.

    T&
    El & despues de un tipo de variable quiere decir, ahora si, que es una referencia. En este caso quiere decir que el operador te devuelve una referencia a algo de tipo T (el contenido del puntero):
    T& operator*() { return *_ptr; }

  13. Julio said

    Es la mejor explicacion de templates que vi en mi vida, y eso que lei un monton por que cuando las vi por primera vez no las podia entender ni un poquitin!

    gfaraj sos un maestro! gracias!

  14. Clelia said

    Que buena informacion has publicado en este blog!!! Esta explicado de forma sumamente sencilla.

    Muchas gracias, continua asi.

  15. carlos said

    excelente…. gracias por las explicaciones… todas son muy utiles!

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>