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

Langage C++ Discussion :

[Metaprog] static const vs enum


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut [Metaprog] static const vs enum
    Salut à tous,
    Jme pose une question, c'est plus une histoire de style qu'autre chose mais bon allons y, quand on travaille en compile-time (metaprog etc) on a besoin de compile-time constant (aucune traduction fr me plait), pour ça on a deux choses soit enum soit static const.
    Jusque là j'ai toujours préféré les enum, d'un parce que je l'ai plus souvent vu, que je suis plus à l'aise (visuellement parlant) avec, de deux parce que seul l'enum est une vraie constante de compilation. Dans le cas d'un static const y'aura une allocation au run tim, donc histoire d'être purement compile-time => enum. (c'est pas de moi, c'est du C++ template the complete guide).
    J'ai toujours vu boost utilisé une macro : BOOST_STATIC_CONSTANT(type, value);
    Jusqu'à ce que je sois curieux et que je me demande ce qu'il y'a derrière cette macro, un grep plus tard (c'est dans boost/config/suffix.hpp) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // BOOST_STATIC_CONSTANT workaround --------------------------------------- //
    // On compilers which don't allow in-class initialization of static integral
    // constant members, we must use enums as a workaround if we want the constants
    // to be available at compile-time. This macro gives us a convenient way to
    // declare such constants.
     
    #  ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
    #       define BOOST_STATIC_CONSTANT(type, assignment) enum { assignment }
    #  else
    #     define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment
    #  endif
    Donc dans le cas général ils préférent (?) utiliser un static const. Y'a-t-il une raison ou c'est purement et simplement une convention qu'ils ont pris?
    Attention, c'est pas parce que boost fait comme ça que je vais changer ma façon de faire hein, à moins que justement y'ai une bonne raison qui mette un au dessus de l'autre.

    Question additionnelle : et vous, où va votre préférence?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Je crois que la raison principale (bien que n'ayant jamais participé au développement de boost), c'est que les deux possibilités (enum vs static const) ont des raisons d'être différentes, et des utilités également différentes.

    Je justifie:

    Tu ne peux pas envisager (me semble-t-il) d'avoir un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <int i>
    struct BlaBla
    {
        static const int value=i;
    };
    Enfin, si, tu peux envisager de l'avoir (le code est valide), mais l'évaluation ne s'effectue plus en compile time, mais bel et bien à l'exécution...

    par contre, tu peux avoir un code (valide) proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <int i>
    struct IntToType
    {
        enum {value = i};
    };
    qui pourrait très bien être utilisée par une autre structure (en compile time) sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <int i>
    struct Truc
    {
         enum {value = (intToType<I>::value==125 ? 125:0)};
    };
    dont l'évaluation pourra être faite au "compile time".

    Autrement dit, si une valeur apparait ailleurs que dans une structure template, le fait d'avoir une énumération ou une valeur statique constante ne changera pas grand chose, hormis la possibilité de s'assurer que toutes les valeurs énumérées ont bel et bien été testées dans le cadre d'un test à choix multiple (switch case)

    Par contre, dans le cas d'une structure template, tu n'auras (me semble-t-il, toujours) pas le choix: tu dois utiliser une énumération
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Ce genre de code est tout à fait valide :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <int i>
    struct BlaBla
    {
        static const int value=i;
    };
    Pour le reste tu as tendance à dire qu'il faut se tourner vers les enum, (j'ai pas bien compris pourquoi tu me parlais de constante en dehors des struct, j'ai du m'emmêler les pinceaux) alors que justement, par défaut (ie en dehors des compilos qui supportent pas l'initialisation de static const à l'intérieur de la classe) boost utilise les static const .

    Et donc non pour te répondre AFAIK les deux fournissent la même chose : une compile-time constant.

    edit : j'avais mal lu, tu dis bien que c'est valide mais que y'aura une évaluation au runtime, ça rejoint ce que je disais. Mais sur son utilisation par contre, (avec ta struct Truc par exemple) alors là par contre ça marche dans les deux cas, static const ou enum.

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Goten Voir le message
    Ce genre de code est tout à fait valide :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <int i>
    struct BlaBla
    {
        static const int value=i;
    };
    Oui, j'ai corrigé mon message entre temps

    Pour le reste tu as tendance à dire qu'il faut se tourner vers les enum, (j'ai pas bien compris pourquoi tu me parlais de constante en dehors des struct, j'ai du m'emmêler les pinceaux) alors que justement, par défaut (ie en dehors des compilos qui supportent pas l'initialisation de static const à l'intérieur de la classe) boost utilise les static const .
    Je récapetete depuis de bedu...

    l'énorme avantage des énumérations par rapport aux constantes statiques tient au fait que le compilateur peut s'assurer que toutes les valeurs énumérées ont bien été testées lors d'un "switch ... case".

    Par exemple, un compilateur bien réglé te sortira un avertissement avec un code proche de
    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
    enum MyEnum
    {
        val1,
        val2,
        val3,
        val4
    };
     
    void foo(MyEnum arg)
    {
        switch(arg)
        {
            case val1: /*blabla*/
                break;
            case val2: /*blabla*/
                break;
            case val3: /*blabla*/
                break;
            /* val4 n'est pas testé */
        }
    }
    parce que, justement, toutes les valeurs ne sont pas testées (val4 ne l'est pas )

    D'autre part, je sais que le résultat d'un test ternaire peut être évalué en compile time sur les énumérations, mais je ne suis pas sur du tout que ce soit le cas lorsque le test se base sur une valeur statique constante...

    Et ce, d'autant plus que les valeurs statiques constantes ont, dans mon esprit du moins, la facheuse manie de vouloir être constantes... indépendemment du type réellement implémenté.

    Je m'explique: je trouve "normal" que npos soit une valeur statique constante dans string_base parce que, que l'on travaille avec la std::string ou avec la std::wstring, la valeur n'a, a priori, pas besoin d'être différente.

    Par contre, dans le cas de la structure IntToType que j'ai présentée plus haut, je trouve "normal" que value soit une valeur énumérée parcequ'elle... varie au gré de la valeur de i...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Ouai, dans le fond, jsuis d'accord avec toi. Mais le problème c'est que, ça va à contre sens de ce que fait boost, (on est d'accord je prends pas tout ce que fait boost comme le code parfait, qu'il faut suivre à tout pris...) puique eux utilise des static const partout.
    Ce que j'en retiens pour l'instant c'est que finalement le comportement est identique (là où tu dis que c'est pas logique d'utiliser static const avec l'op ternaire, ça marche que même) donc, c'est plus un choix empirique qu'autre chose. Un jour j'aimerais quand même ce qui a poussé les dev de boost à faire celui là.

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Goten Voir le message
    Ouai, dans le fond, jsuis d'accord avec toi. Mais le problème c'est que, ça va à l'encontre de ce que fait boost. (on est d'accord je prends pas tout ce que fait boost comme le code parfait, qu'il faut suivre à tout pris...)
    Attention...

    Ce n'est pas parce que l'énumération est utilisée si un symbole est défini qu'il faut estimer que, d'office, le symbole ne l'est pas par défaut...

    Sur base des cinq lignes de codes dont on dispose, il est difficile de savoir si BOOST_NO_INCLASS_MEMBER_INITIALIZATION est défini par défaut ou non (il faudrait sans doute aller voir dans un config.h quelconque, voir dans les jamfiles )

    Peut être fais tu, justement, erreur, et remarque-t-on que, par défaut, c'est l'énumération qui sera mise en oeuvre

    [EDIT]Et encore, s'agissant d'une compilation conditionnelle, on peut tout aussi bien estimer qu'il sera défini pour un compilateur ou une version de compilateur particulière et non défini pour un(e) autre, voire, défini pour une majorité et non défini pour une minorité (ou l'inverse)....
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. enum et static const
    Par oodini dans le forum Langage
    Réponses: 9
    Dernier message: 06/09/2011, 09h19
  2. rendre static const un attribut hérité ?
    Par JujuTh dans le forum C++
    Réponses: 6
    Dernier message: 08/07/2007, 16h02
  3. Réponses: 2
    Dernier message: 30/10/2006, 16h40
  4. Réponses: 1
    Dernier message: 23/09/2006, 00h41
  5. static const et taille de tableau
    Par tut dans le forum C++
    Réponses: 3
    Dernier message: 27/01/2005, 16h01

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