2010-08-20 20 views
2

que j'ai trouvé quelques étranges C++ clauses de préprocesseur, comme:Que fait "#define FOO (template)"?

#define COMPILER_FLOAT_ENTRIES_DO(template) 

et

#define COMPILER_FLOAT_ENTRIES_DO(template) \ 
    template(jvm_fadd) \ 
    template(jvm_fsub) \ 
    template(jvm_f2d) 

Que signifie passage "modèle" mot réservé à un #define, et appelant modèle (quelque chose) signifie? Je n'ai rien trouvé chez Google. probablement parce que "#define" et "template" sont des mots vraiment communs.

L'intégralité du code est https://phoneme.dev.java.net/source/browse/phoneme/components/cldc/trunk/src/vm/share/ROM/ROMWriter.hpp?rev=19839&view=markup.

+2

Lors d'une conjecture sauvage, malgré le fichier spécifique apparaissant à rapporter à C++, cet ensemble macro s'origine dans un environnement C où 'template' n » t un mot réservé.Même en C++, il n'est pas vraiment réservé à la phase du préprocesseur, mais il serait généralement considéré comme une mauvaise pratique d'utiliser un mot réservé comme nom de macro ou paramètre formel comme cela est fait ici en raison du risque de confusion. – RBerteig

Répondre

6
#define COMPILER_FLOAT_ENTRIES_DO(template) 

alors COMPILER_FLOAT_ENTRIES_DO(x) est remplacé par ''. En d'autres termes, il supprime cette macro du code.

#define COMPILER_FLOAT_ENTRIES_DO(template) \ 
    template(jvm_fadd) \ 
    template(jvm_fsub) \ 
    template(jvm_f2d) 

si COMPILER_FLOAT_ENTRIES_DO(x) sera remplacé par x(jvm_fadd) x(jvm_fsub) x(jvm_f2d).

Si tout le reste échoue, vous pouvez voir ce qui se passe avec les macros en utilisant g++ -E -o foo.cpp pour quitter la sortie du pré-traitement de macro dans foo.cpp. Bien sûr, vous aurez besoin de tous les autres drapeaux de compilation passés en ligne de commande (en particulier les drapeaux -D et -I).

9

Le mot "template" est une coïncidence ici. Le préprocesseur n'est pas sensible aux mots réservés de cette manière, car il ne fait que des opérations de texte.

C'est une macro standard qui prend un nom de fonction comme argument et appelle cette fonction trois fois avec ces arguments. La première version avec rien après ressemble à une version de débogage ou à une autre version conçue pour en faire un non-op dans un certain contexte.

3

Vous trouvez souvent ce type de codage dans les modèles de conception de programmation pilotée par les données.

Ceci est pratique lorsque vous souhaitez inclure plusieurs fois le même fichier (Data) mais où les macros sont remplacées par du code différent ou d'autres données.

Supposons que certains attributs et types respectifs là:

/// @file data.h 
my_attribute(color, int) 
my_attribute(volume, float) 

La partie codante peut utiliser les données sans même avoir besoin de connaître la quantité. À titre d'exemple, imprimons quelques informations.

/// @file main.c 
void help() 
{ 
    #define my_attibute(name,type) cout << #name << ": " << #type << endl; 
    cout << "available attributes:" << endl; 
    #include "data.h" 
    #undef my_attribute 
} 

(notez le #name est utilisé pour obtenir la chaîne de texte "couleur" au lieu d'une valeur color)

De cette façon, votre code est indépendant de données.

Edit: typo fix et phrase en anglais selon @RBerteig

+0

D'après mon expérience, je dirais «souvent» plutôt que «habituellement». C'est une partie essentielle de la technique que vous démontrez. Mais ce n'est pas la seule utilisation pour les macros avec paramètres, et le cas de l'OP est plus susceptible d'être une sorte d'optimisation pour une architecture matérielle spécifique où l'opération est inutile dans une architecture, et mieux implémentée par un texte source qui ressemble à trois appels de fonction (mais probablement trois déclarations 'asm'-ish) dans une autre architecture. – RBerteig