IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Utiliser un template sans préciser ses paramètres


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut Utiliser un template sans préciser ses paramètres
    Bonjour,

    J'ai eu du mal à formuler ce titre et j'ai un peu de mal à formuler mon problème... Je vois souvent des intérêts aux templates pour figer la taille de certains éléments à la compilation. Comme je travaille en embarqué, ça me permet de figer à la compilation la mémoire nécessaire et d'éviter l'allocation dynamique. Mon problème est que je vois pas comment utiliser facilement le type template en paramètre ou retour d'autres fonctions sans mettre tout le monde template.

    Un petit code sera plus clair je pense :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    template<unsigned int icon_count>
    class StatusBar
    {
        void setIcon(unsigned int index, bool on)
        {
            // bla bla
        }
     
        unsigned int getIconCount()
        {
            return icon_count;
        }
    };
     
    StatusBar<5> my_bar;
     
    StatusBar<?> getStatusBar()
    {
        return my_bar;
    }
     
    void init()
    {
        StatusBar<?> bar = getStatusBar();
        for (unsigned int i = 0; i < bar.getIconCount(); ++i)
        {
            bar.setIcon(i, false);
        }
    }
    Pour rester plus "standard", on peut faire la même chose avec array de <array>. En admettant qu'on spécialise sur le paramètre de type mais pas sur la taille, on ne peut toujours pas le passer à des fonctions non templates (la taille n'est pas un problème, on peut la récupérer auprès de l'objet).

    Est-il possible de réaliser un tel code ? Si oui, comment ? Si non, il me reste donc à oublier définitivement ce genre d'idées

    Merci d'avance !

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Salut!

    Non, on ne peux pas ne pas préciser complètement la template utilisée sans être template du reste soi-même.
    Il faut bien comprendre qu'une template n'est pas du code concret, et que StatusBar<1> n'est pas la même classe que StatusBar<5>.


    Par contre, tu peux utiliser la déduction automatique de type, avec le mot-clé auto.
    En effet, ce qui est important pour le développeur, ce n'est pas le type précis de la valeur, mais sa signification. Le compilateur connaît très bien son type, c'est son travail.

    Selon la norme que tu utilises, il peut être nécessaire de préciser le "trailing type", voici la syntaxe:
    • C++11: auto getStatusBar() -> decltype(m_bar) { return my_bar; }
    • C++14: auto getStatusBar() { return my_bar; }

    Je ne sais plus sous quelle condition il faut utiliser le trailing type, essaye sans le compilateur râlera s'il est nécessaire.

    De même, dans init(), bar peut être définie par auto bar = getStatusBar(); ou auto const bar = getStatusBar();.

    La règle est que auto est utilisable dans chaque définition où une valeur fournit le type à utiliser.
    Ainsi, il n'est pas possible de déclarer une fonction retournant auto sans la définir immédiatement.

    Cette astuce est également valable dans la définition de template.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <typename A, typename B> auto add(A a, B b) { return a + b; }

    D'un autre côté, je trouve dérangeant d'avoir un type template dans du code "métier".
    Quand bien même ce serait le type adapté, je préfère de très loin avoir un alias de type portant un nom métier.
    Le type que le métier manipule n'est pas StatusBar<5> mais le StatusBar-qui-va-bien, par exemple DetectorStatusBar.

    En général, dans les applications que je manipule, j'ai visiblement trois couches de types:
    • Les types purement techniques, définis par des templates.
    • Les types auxiliaires du métier, souvent des capsules autour de templates comme vector, mais parfois des typedef vers ces types.
    • Les types purement métier (ou logiques), non template, car la couche métier répond à un besoin précis.


    La frontière entre les deux premières parties est parfois un peu floue, mais quoi qu'il advienne, si j'ai une valeur dont le type est une instance d'une template, je refuse qu'apparaisse son origine template dans le code qui s'en sert.

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Par ailleurs, ca me fait tout drôle de répondre à tes questions, après avoir appris autant de tes explications en C.

  4. #4
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    Si je puis me permettre d'ajouter quelque chose aux explications super claires du ternel,
    je dirais que face à ce genre de situation ma réponse simple est : héritage !

    Tu déclares une classe (abstraite ou non) dont héritent toutes les instances de ta classe template.
    Voici un petit exemple qui vaut mieux qu'un long charabia :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    struct g_popable
        {
        virtual bool isempty () const = 0 ;
        virtual int pop () = 0 ;
        };
     
    template <unsigned N> class stack : public g_popable
        {
        public:
            bool isempty () const ;
            bool isfull () const ;
            void push ( int x ) ;
            int  pop () ;
        protected:
            int _top,_table [N] ;
        };
     
    int foo ( g_popable & popable )
        {
        if (!popable.isempty())
            return popable.pop() ;
        return -1 ;
        }
     
    int main ()
        {
        stack<30> s1 ;
        stack<20> s2 ;
        s1.push( 5 ) ;
        return foo( s1 ) + foo( s2 ) ;
        }
    Voilà, je ne sais pas si cette solution peut s'appliquer à ton problème, mais moi, je l'aime bien...

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    En effet, tu peux, mais tu paies le prix du virtual, ce qui est dommage.

    Cela dit, la classe de base non template n'est pas une mauvaise idée. Tout particulièrement si on peut y placer un comportement non virtuel.

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Effectivement, un code avec auto fonctionne bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    template<unsigned int icon_count>
    class StatusBar
    {
    public:
        void setIcon(unsigned int index, bool on)
        {
            // bla bla
        }
     
        unsigned int getIconCount()
        {
            return icon_count;
        }
    };
     
    StatusBar<5> my_bar;
     
    auto getStatusBar() -> decltype(my_bar)
    {
        return my_bar;
    }
     
    void init()
    {
        auto bar = getStatusBar();
        for (unsigned int i = 0; i < bar.getIconCount(); ++i)
        {
            bar.setIcon(i, false);
        }
    }
    Bon le hic c'est que je suis en C++03 mais ceci est une autre histoire

    La réflexion sur les couches logicielles où utiliser des templates et ou ne pas les utiliser est intéressante. Je vais la considérer dans mon design. Surtout que la plupart des cas où je voudrais faire ça est pour fixer des tailles à la compilation, ce que je pourrais faire avec des constantes fournies au code de différentes manières.

    L'idée de la classe d'interface par dessus le template est intéressante aussi. Elle ne résout pas mon problème a priori mais ça me donne un autre angle de vision.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Il faut bien comprendre qu'une template n'est pas du code concret, et que StatusBar<1> n'est pas la même classe que StatusBar<5>.
    Il faut vraiment que je me mette ça dans la tête... Pour l'instant, j'ai la logique Java dans la tête, où les parameterized types sont des sous-types du generic type qu'ils spécialisent.

    Merci pour vos réponses !

Discussions similaires

  1. Réponses: 11
    Dernier message: 26/02/2015, 01h20
  2. [AC-2007] Utiliser deux champs calculés pour créer un nouveau calcul sans passage de paramètre
    Par shakapouet dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 28/04/2014, 09h24
  3. [2008R2] Utilisation d'une procédure avec ses paramètres contenu une table
    Par bisou007 dans le forum Développement
    Réponses: 0
    Dernier message: 01/07/2013, 17h07
  4. Peu-t-on utiliser DIM sans préciser le type
    Par Henri-gp dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 26/07/2012, 11h11
  5. Réponses: 5
    Dernier message: 31/10/2008, 12h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo