7

Initialement, je pensais avoir besoin de cela, mais je l'ai finalement évité. Cependant, ma curiosité (et l'appétit pour le savoir, hum) me font demander:Extension de macros de préprocesseur à une autre directive de préprocesseur

une macro préprocesseur peut, par exemple dans

#include "MyClass.h" 

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass) 

étendre à l'autre comprennent, comme dans

#include "MyClass.h" 

#include "FooTemplate.h" 
template class FooTemplate<MyClass>; 

?

+2

Un jour, vous voudrez transférer votre code vers un système d'exploitation comme Linux où cas est significatif (par exemple, Foo.h et foo.h sont deux fichiers différents), puis toutes les fautes d'orthographe qui ne sont pas capturés sur Windows viendront à la maison perchoir. Alternativement, si vous êtes une personne Linux, vous voudrez un jour aller dans l'autre sens, avec des problèmes différents mais tout aussi horribles. –

+1

Je suis d'accord avec la règle toujours-minuscule pour les noms de fichiers. J'ai écrit ainsi parce que je voulais exclure le problème de la conversion en minuscules (nom de la classe -> nom du fichier). Mais cela vaut la peine de mentionner, merci. +1! – moala

+0

Notre règle est que les noms de fichiers correspondent exactement au schéma de nommage de nos types et de nos fonctions. Nous faisons exactement comme le questionneur ici, un nom de type FooType sera défini dans FooType.h. Comme pour toute ligne directrice «style», choisissez un style et respectez-le. Cela dit, nous développons beaucoup sur linux et donc cette règle est automatiquement appliquée pour nous par l'OS .... hmmmmm ..... –

Répondre

12

Je crois que cela ne peut pas être fait, c'est parce que le pré-processeur est seul passage. Il ne peut donc pas émettre d'autres directives de préprocesseur.

Plus précisément, de la norme C99 (6.10.3.4 paragraphe 3):

3 Le résultat complètement séquence macro-jeton remplacé prétraiter n'est pas traitée comme une directive de pré-traitement même si elle ressemble à un , ...

Fait intéressant, c'est pourquoi l'opérateur unaire _Pragma a été ajouté à c99. Parce que #pragma n'a pas pu être émis par les macros, mais _Pragma peut.

+0

Eh bien, il peut bien sûr émettre les directives. ce qu'il ne peut pas faire est de les traiter dans le même passage du préprocesseur. –

+1

Puisque les caractères '#' et '##' ont des significations spéciales dans les macros, je ne vois pas comment vous pourriez réellement émettre une directive ... –

+0

En fait, le préprocesseur GCC semble autoriser "#define X #ifdef X" où l'espace entre le #ifdef et le second X est vraiment un retour à la ligne, et cela émet un #ifdef quand vous lancez cpp dessus. Quelqu'un d'autre pourrait vouloir vérifier cela, car je viens d'avoir quelques bières :-) –

9

La norme C dit ceci au sujet des directives prétraiter (C99 - 6.10 (2) - directives Prétraitement):

Une directive de pré-traitement consiste en une séquence de jetons de pré-traitement qui commence par un jeton # de pré-traitement que (au début de la phase de traduction 4) ...

et (C99 - 6,10 (7)):

Les jetons de prétraitement dans une directive de prétraitement ne sont pas soumis à l'extension macro , sauf indication contraire.

EXEMPLE Dans:

#define EMPTY 
EMPTY # include <file.h> 

la séquence de jetons de pré-traitement sur la deuxième ligne n'est pas une directive de pré-traitement, car elle ne commence pas par un # au début de la phase de traduction 4, même si elle fera donc après que la macro EMPTY a été remplacée

Donc, non, les macros ne peuvent pas développer dans une directive de prétraitement '#include'. Ces directives doivent être en place au début de la phase de traduction 4 (lors du traitement de ces directives, il se produit un prétraitement). Depuis l'expansion macro se produit pendant la phase 4, les macros ne peuvent pas faire quelque chose d'exister au début de la phase 4.

Je voudrais souligner toutefois que le ci-après ne travail:

#ifdef WIN32 
#define PLATFORM_HEADER "platform/windows/platform.h" 
#else 
#define PLATFORM_HEADER "platform/linux/platform.h" 

#include PLATFORM_HEADER 

parce que le standard C le dit (C99, 6.10.2 (4) - l'inclusion du fichier source):

Une directive de pré-traitement de la forme

# include pp-tokens new-line 

(qui ne correspond pas à l'une des deux formes précédentes) est autorisée. Les jetons de prétraitement après inclusion dans la directive sont traités comme dans le texte normal. (Chaque identificateur actuellement défini comme un nom de macro est remplacée par la liste de remplacement des jetons de pré-traitement.)

+0

J'ai regardé cette partie de la norme, mais je ne pense pas que ce soit la section la plus pertinente. L'exemple n'est pas celui qui essaie d'émettre une directive. Il s'agit plutôt d'un exemple de directive qui n'est pas précédé d'un "espace" (même si la macro EMPTY se résout en espaces). –

+1

Je serais d'accord que votre citation de la norme est plus directement pertinente, mais il n'y avait pas là quand j'ai répondu.Même si l'exemple ci-dessus n'est pas identique à ce qui est demandé, le bit sur la directive de prétraitement qui doit être en place au début de la phase 4 interdit également aux macros de s'expliquer en directives de prétraitement utiles, même si 6.10.3.4 (3) dit plus directement. (en d'autres termes, même si je ne pense pas que ma réponse soit incorrecte, la vôtre est clairement une meilleure réponse). –

+0

Assez juste, vous faites un bon point, +1 :-). –

1

Toutes les directives de préprocesseur sont interprétés avant l'expansion macro COMMENCE, donc pas, vous ne pouvez pas avoir une macro se développer dans un # inclure la directive et l'interpréter comme telle. Au lieu de cela, il sera interprété comme un code C++ (erroné).

+0

Vous pourriez obtenir cette impression car de nombreuses directives désactivent l'expansion de macro de leurs arguments, mais ce n'est pas le cas. L'expansion de la macro se produit en même temps que l'analyse de la directive. Si c'était vrai, #if ne fonctionnerait pas, et #undef n'aurait pas l'effet escompté. – zwol

Questions connexes