2010-10-15 22 views
3

Alors disent que je suis la macro suivante très simple, avec un peu de code pour le sortir:C++ macros constantes préprocesseur et modèles

#define SIMPLEHASH(STRING) STRING[1] + STRING[2] + STRING[3] 
std::cout << SIMPLEHASH("Blah"); 

Ce sorties 309, et si vous affichez l'assemblage, vous pouvez voir:

00131094 mov   ecx,dword ptr [__imp_std::cout (132050h)] 
0013109A push  135h 
0013109F call  dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13203Ch)] 

135h traduit bien en 309 décimales. Tout a été compilé à une constante.


Maintenant, supposons que vous avez une classe de modèle en tant que tel:

template<int X> class Printer{ 
public: 
void Print(){ 
    std::cout << X; 
} 
}; 

les commandes suivantes vont bien imprimer le numéro 32:

Printer<32> p; 
p.Print(); 

Ces deux choses fonctionnent individuellement , le problème vient quand vous essayez de les combiner:

#define SIMPLEHASH(STRING) STRING[1] + STRING[2] + STRING[3] 
Printer<SIMPLEHASH("Blah")> p; 
p.Print(); 

en studio visuel ce qui donne:

1> \ ShiftCompare.cpp (187):. Erreur C2975: 'X': argument modèle invalide pour l'imprimante », attendue compilation expression constante
1> \ ShiftCompare.cpp (127). voir la déclaration de « X »

Malgré le fait que SIMPLEHASH("Blah") peut être réduit à une constante lors de la compilation, comme on le voit dans le premier exemple. Alors, qu'est-ce qui donne, est-ce qu'il y a un moyen de dire au compilateur "évaluez ceci en premier"? les modèles sont-ils naturellement "avant" les macros dans l'évaluation du préprocesseur?

Est-ce que quelqu'un voit d'une quelconque façon que je peux obtenir ces deux pour travailler ensemble?

+1

Le préprocesseur est un hareng rouge. Selon le langage, «Blah» [0] 'n'est pas une expression constante; c'est tout. Juste parce que votre compilateur est arrivé à comprendre cela ne veut rien dire. (Et c'est le problème de prendre des résultats spécifiques à la mise en œuvre et en supposant qu'il est garanti par la langue.) – GManNickG

+2

Pour répondre à la question "comment puis-je faire travailler ensemble ces deux-là?" En partie, il serait utile que vous puissiez expliquer le problème que vous essayez de résoudre. Si vous ne pouvez pas _literally_ obtenir ces deux choses pour travailler ensemble, vous pourriez être en mesure de résoudre votre problème par d'autres moyens. –

+0

Était en train d'essayer de faire fonctionner une fonction de hachage pour créer des alias (au moment de la compilation) pour l'enregistrement dans une classe d'usine. J'essayais de donner aux classes qui ont besoin d'être enregistrées un membre statique (classe modèle). ce membre peut enregistrer sa classe propriétaire quand son constructeur a été appelé (étant statique, immédiatement sur le chargement du code). L'autre façon évidente est d'utiliser des globals plutôt que des membres statiques, et cela fonctionne bien, je voulais juste voir s'il y avait un moyen qui ne laissait pas les globals voler dans l'espace de noms. – Jason

Répondre

5

Les macros sont évaluées avant l'analyse complète de la source et le prétraitement n'a absolument rien à voir avec les modèles.

Le problème est que l'argument de modèle avec lequel vous instanciez Printer doit être une expression constante et vous ne pouvez pas utiliser un littéral de chaîne dans une expression constante.