59 votes

Métaprogrammation par modèles - Différence entre l'utilisation de Enum Hack et de Static Const

Je me demande quelle est la différence entre l'utilisation d'une const statique et d'une enum hack lors de l'utilisation de techniques de métaprogrammation de templates.

EX : (Fibonacci via TMP)

template< int n > struct TMPFib {
  static const int val =
    TMPFib< n-1 >::val + TMPFib< n-2 >::val;
};

template<> struct TMPFib< 1 > {
  static const int val = 1;
};

template<> struct TMPFib< 0 > {
  static const int val = 0;
};

vs.

template< int n > struct TMPFib {
  enum {
    val = TMPFib< n-1 >::val + TMPFib< n-2 >::val
  };
};

template<> struct TMPFib< 1 > {
  enum { val = 1 };
};

template<> struct TMPFib< 0 > {
  enum { val = 0 };
};

Pourquoi utiliser l'un plutôt que l'autre ? J'ai lu que le hack enum était utilisé avant que static const ne soit supporté à l'intérieur des classes, mais pourquoi l'utiliser maintenant ?

1 votes

+1 : une excellente question en effet, et j'aimerais également voir quelles seront les réponses, à l'exception de celles qui sont évidentes.

4 votes

Static const autorise les types autres que int. double par exemple.

39voto

Georg Fritzsche Points 59185

Les énumérations ne sont pas des intervalles, les valeurs statiques des membres le sont et si elles sont transmises par référence, le modèle sera instancié :

void f(const int&);
f(TMPFib<1>::value);

Si vous souhaitez effectuer des calculs au moment de la compilation, etc., il s'agit d'un effet secondaire indésirable.

La principale différence historique est que les enums fonctionnent également pour les compilateurs qui ne prennent pas en charge l'initialisation des valeurs des membres dans la classe, ce qui devrait être corrigé dans la plupart des compilateurs.
Il peut également y avoir des différences de vitesse de compilation entre les constantes enum et les constantes statiques.

Il y a quelques détails dans le renforcer les lignes directrices en matière de codage et un fil de discussion plus ancien dans les archives de boost sur le sujet.

0 votes

Je ne sais pas si c'est toujours vrai, en regardant la sortie du compilateur (godbolt), les deux extraits donnent le même code assembleur.

12voto

Kornel Kisielewicz Points 26556

Pour certains, le premier peut sembler moins astucieux et plus naturel. De plus, il a de la mémoire allouée pour lui-même si vous utilisez la classe, vous pouvez par exemple prendre l'adresse de val.

Ce dernier est mieux supporté par certains compilateurs plus âgés.

0 votes

Merci. C'est exactement le genre de réponse que je cherchais.

1 votes

Personnellement, je ne suis pas du tout d'accord. La version enum semble plus naturelle. Pourquoi a-t-on besoin d'une variable physique ? Enum est la représentation d'une valeur constante. L'utilisation d'un static const int ressemble plus à un retour en arrière à l'époque où nous devions utiliser des macros pour représenter des valeurs constantes.

3 votes

@Martin, quel est le rapport entre le mot-clé énumération et le calcul ? Mais j'ai bien compris - chacun peut avoir son propre point de vue sur la question.

2voto

Dan H. Points 129

Le revers de la médaille @Georg Lorsqu'une structure contenant une variable statique constante est définie dans un modèle spécialisé, elle doit être déclarée dans le code source afin que l'éditeur de liens puisse la trouver et lui donner une adresse à laquelle elle peut être référencée. Cela peut inutilement (en fonction des effets souhaités) provoquer un code inélégant, en particulier si vous essayez de créer une bibliothèque d'en-têtes uniquement. Vous pourriez résoudre ce problème en convertissant les valeurs en fonctions qui renvoient la valeur, ce qui pourrait ouvrir les modèles aux informations d'exécution également.

0voto

djacob Points 110

Le "hack enum" est une méthode plus contraignante et plus proche de l'idée de "hack". #define et cela permet d'initialiser l'énumération une fois et il n'est pas légal de prendre l'adresse d'une énumération. enum n'importe où dans le programme et il n'est généralement pas légal de prendre l'adresse d'un #define non plus. Si vous ne voulez pas permettre aux gens d'obtenir un pointeur ou une référence à l'une de vos constantes intégrales, l'option enum est un bon moyen d'appliquer cette contrainte. Pour voir comment impliquer à TMP que pendant la récursion, chaque instance aura sa propre copie de l'élément enum { val = 1 } pendant la récursivité et chacun de ces val aura sa place dans sa boucle. Comme @Kornel Kisielewicz l'a mentionné, le "hack de l'enum" est également supporté par les anciens compilateurs qui interdisent la spécification en classe des valeurs initiales de ces éléments. static const .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X