• [^] # Re: C & Cie

    Posté par . En réponse à la dépêche Sortie de Vala 0.1.6. Évalué à 3.

    C'est simplement que ce n'est pas la même technique, chacun apportant une réponse à des cas particuliers, en particulier ce qui justifie l'utilisation des templates c'est que dès la compilation, on sait quelles méthodes vont être appelées. Si on reprend l'algorithme de tri, avec des interfaces on a vu qu'on utilisait un une classe héritant de Comparator qui est une interface, si je veux implémenter mon propre comparator, je ferai :


    class MonComparator : public Comparator
    {
    int compare(Object o1, Object o2)
    {
    /* le code qui fait la comparaison */
    }
    };

    Pour trier on va alors instancier un objet MonComparator et le passer à la fonction Collection.sort().


    Avec les templates, l'algorithme std::sort prend en paramètre une fonction, non pas un pointeur de fonction comme c'est le cas en C avec la fonction qsort mais un nom de fonction, le compilateur étant en charge de générer le code avec la bonne fonction. la declaration de std::sort ressemble à ça :

    template <typename Iterator, typename Compare>
    void sort (Iterator first, Iterator end, Compare comp);

    Si je veux créer mon propre comparateur, je vais écrire :
    struct MonComparateur
    {
    bool operator()(int i1, int i2)
    {
    /* code de comparaison */
    }
    };


    Pour trier on va alors faire

    std::sort(collection.begin(), collection.end(), MonComparateur());


    A la compilation, on déclare une nouvelle fonction sort qui prend en troisième paramètre une classe de type MonComparateur.

    Les différence entre les deux approches :
    - La principale c'est que l'approche template implémente une nouvelle fonction std::sort pour chaque types de paramètres différents, si je réutilise ma fonction std::sort() avec un autre comparateur (std::less par exemple), j'aurai une deuxième fonction sort prenant des paramêtres différents.
    - Avec les templates, mon comparateur compare directement le type qu'il souhaite et n'a pas besoin de "caster" les Object vers le type souhaiter, on a donc une erreur dès la compilation en cas d'utilisation d'un comparateur sur un mauvais type (ceci n'est plus vrai il me semble en Java5 et en .Net2, l'interface Comparator étant une interface generique qui prend en paramètre le type comparé).


    C'est vraiment important de saisir qu'avec les template, à chaque appel à une fonction avec des paramêtre différent, le compilateur crée un nouvelle fonction qui s'appel de la même façon que si elle était apellée directement.

    C'est un exemple volontairement simple qui ne couvre pas tout ce qu'on peut faire ni avec l'héritage, ni avec les templates mais qui, je l'espère, permet de saisir la différence technique.