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 :

Métaprogrammation : taille d'un tableau


Sujet :

C++

  1. #1
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut Métaprogrammation : taille d'un tableau
    Bonjour,

    Je souhaite utiliser dans mon code, des tableaux statiques constants.
    Mon problème est de parcourir ces tableaux : pour cela, il me faut leur taille.

    Mon idée première était de créer une méthode template qui me renverrait la taille d'un tableau. Quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T, int i, T[i]>
    int GET_ARRAY_SIZE()
    {
       return i;
    };
    Cependant, je ne peux pas appeler cette méthode sans lui fournir i, c'est à dire la taille de mon tableau, c'est à dire précisément ce que je cherche à obtenir.

    Je me suis donc rabattu sur un check qui vérifie que mon tableau est bien de la taille que je crois :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    template<typename T, int i, T[i]> struct CHECK_ARRAY_SIZE{};
    que j'utilise comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    //------------ header ------------
    class A
    {
        // mon tableau et sa taille
        static const float m_MyArray[];
        static const int m_iMyArraySize;
     
        // une fonction dans laquelle je vais m'en servir
       void m();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    //------------ body------------
    const int A::m_iMyArraySize = 3;
    const float  A::m_MyArray[] = {2.4F,3.7F,6.2F};
     
    void A::m()
    {
        CHECK_ARRAY_SIZE<const float,m_iMyArraySize,m_MyArray> a;
    }
    Tout ceci marche parfaitement bien et compile sauf si je la taille de mon tableau n'égale pas m_iMyArraySize.

    Mon problème est que je n'arrive pas à l'utiliser avec des tableaux de char*, pour une raison sans doute évidente mais qui m'échappe :

    ainsi le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    //------------ header ------------
    class A
    {
        // mon tableau et sa taille
        static const char* m_MyArray[];
        static const int m_iMyArraySize;
     
        // une fonction dans laquelle je vais m'en servir
       void m();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    //------------ body------------
    const int A::m_iMyArraySize = 4;
    const char* A::m_MyArray[] = {"joe","jack","william","averell"};
     
    void A::m()
    {
        CHECK_ARRAY_SIZE<const float,m_iMyArraySize,m_MyArray> a;
    }
    provoque l'erreur de compilation :
    error C2975: 'function-parameter' : argument de modèle non valide pour 'CHECK_ARRAY_SIZE', expression de constante évaluée au moment de la compilation attendue
    Je suppose que ça a un rapport avec le fait que si le pointeur est const, la donnée qui pointe ne l'est pas forcément, et donc elle ne peut être évaluée à la compilation, mais je n'arrive pas à trouver comment faire que cela marche.

    Quelqu'un aura-t-il une piste pour me sortir d'affaire ?

    Merci d'avoir lu ce post,
    Merci à ceux qui voudront bien m'aider.

  2. #2
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Mea maxima culpa.

    En fait cela marche, c'est juste que j'utilisais la mauvaise variable, et donc cela plantait exactement comme je voulais que ça plante.

    Bon ben je vais aller me jeter.
    Merci à tous

  3. #3
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Le nombre d'elements dans un tableau C, c'est sizeof(tab)/sizeof(*tab).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  4. #4
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Merci pour cette réponse.

    Je croyais avoir de bonnes raisons de ne pas utiliser sizeof, mais en essayant de les écrire, elles se sont évanouies.

    Merci donc.

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En C++, tu peux faire plus sûr pour obtenir la taille d'un tableau, grâce aux templates.
    C'est ainsi qu'est faite la macro ARRAYSIZE() de Visual:
    http://www.developpez.net/forums/sho...87&postcount=6
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    http://hermitte.free.fr/Info/C++/lib..._help.hpp.html

    Pour la fonction begin(), il faut rajouter un +0 à ce que l'on veut renvoyer selon les compilos. De toutes façons, c'est dans boost.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #7
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Merci pour ces réponses qui cadrent plus avec ce que je voulais faire originalement.

    Si vous repassez par ici, je me permets d'abuser de vos lumières en vous demandant des précisions sur ces deux codes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <std::size_t N>
            struct array { char value[N]; };
    template<typename T, std::size_t N>
            array<N> array_size_helper(T (&)[N]);
    #define array_size(array) (sizeof luc_lib::array_size_helper(array).value)
    Si je comprend bien, l'idée est que la fonction array_size_helper : plutôt que de renvoyer directement la taille du tableau, renvoie une structure contenant un tableau de char de la même taille.
    La macro donne la taille de ce tableau en octets, et comme la taille d'un char doit être 1 octet, c'est aussi la taille du tableau en nombre d'éléments.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template< class T, size_t N >
    		char (* TArraySize(T (&tab)[N]) )[N];
    #define ARRAYSIZE(arr) sizeof(*TArraySize(arr))
    Si j'ai bien compris, il s'agit de la même stratégie : une méthode qui renvoie un tableau de char de la même taille que le tableau passé en paramètre + une macro qui fait le sizeof de ce tableau retourné.


    Question 1 : pourquoi est-ce plus efficace et/ou sécuritaire qu'un sizeof(array)/sizeof(élément) ?

    Question 2 : pourquoi passer par sizeof. Si la méthode array_size_helper renvoyait directement N, ne pourrait-elle pas être évaluée à la compilation ? Pourquoi ?

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Luc : (edit : J'ai rien dit)

    Feriaman :
    1. Parce que sizeof/sizeof "marche" sur les pointeurs, retournant, au lieu de la taille du tableau, la taille du pointeur divisée par la taille d'un élément pointé. ARRAYSIZE() en template évite ce problème en provoquant une erreur de compilation si on tente de l'utiliser sur autre chose qu'un tableau.
    2. array_size_helper ne "renvoie" rien du tout, et n'est même jamais appelée. ARRAYSIZE() ne fait que consulter la taille de ce que array_size_helper renverrait si on l'appelait avec un tel tableau. Et cette taille est vraiment constante, connue à la compilation, alors qu'un résultat de fonction ne l'est jamais.


    PS: La version de Luc a l'avantage d'être plus lisible que celle de Microsoft que j'ai recopiée de mémoire.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Merci encore : C'est très clair.

  10. #10
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par Médinoc
    Luc : (edit : J'ai rien dit)
    Ca tombe bien, je n'ai ren vu

    PS: La version de Luc a l'avantage d'être plus lisible que celle de Microsoft que j'ai recopiée de mémoire.
    Dire que "la version de Luc" est un peu abusé. J'avais repompé ça sur fclc++ il y a quelques temps déjà. D'ailleurs pour avoir plus d'infos, cherchez le m-id donné dans mon fichier via groups.google.com ; il doit y avoir un petit thread sympa à lire dans mes souvenirs.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Tableau]comment connaitre la taille d'un tableau à 2 dimensions
    Par Kyti dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 22/04/2005, 10h27
  2. Changer la taille d'un tableau déjà initialisé
    Par totofweb dans le forum C++
    Réponses: 2
    Dernier message: 25/07/2004, 15h55
  3. taille d'un tableau
    Par monstour dans le forum ASP
    Réponses: 3
    Dernier message: 24/06/2004, 15h16
  4. Taille maximum de tableau en Delphi
    Par yannick37 dans le forum Langage
    Réponses: 5
    Dernier message: 03/03/2004, 13h18
  5. qbasic : taille d'un tableau
    Par clood200 dans le forum Basic
    Réponses: 2
    Dernier message: 16/09/2003, 07h26

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