Pragma dans définir la macro

99

Existe-t-il un moyen d'intégrer une instruction pragma dans une macro avec d'autres instructions?

J'essaye de réaliser quelque chose comme:

#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type_(int handle);                  \
    void delete_ ## type(int handle);                                                \
    #pragma weak delete_ ## type_ = delete_ ## type

Je suis d'accord avec les solutions de boost (sauf pour la vague) s'il en existe.

Anycorn
la source
5
On peut soutenir que ce n'est ni l'un ni l'autre - les #pragmas ne sont définis ni par les normes C ni par les normes C ++.
Le préprocesseur est, même si la sous-commande autorisée spécifique qu'il veut exécuter ne l'est pas.
Puppy
@DeadMG: Il y a beaucoup de choses communes entre C et C ++. Alors que le prétraitement est principalement courant, il existe des différences majeures dans la façon dont le prétraitement est spécifié en fonction du standard de langage utilisé (C89, C99, C ++ et le C ++ 0x FCD).
James McNellis
2
@James McNellis: Simplement parce que techniquement, la plupart des programmes C sont portables en C ++, cela ne rend pas cette fonctionnalité véritablement courante, car aucun programmeur C ++ n'en ferait la grande majorité. Les deux langues n'ont en fait pas grand-chose en commun.
Puppy

Réponses:

116

Si vous utilisez c99 ou c ++ 0x, il y a l'opérateur pragma, utilisé comme

_Pragma("argument")

ce qui équivaut à

#pragma argument

sauf qu'il peut être utilisé dans les macros (voir section 6.10.9 du standard c99, ou 16.9 du projet final du comité c ++ 0x)

Par exemple,

#define STRINGIFY(a) #a
#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type ## _(int handle);                  \
    void delete_ ## type(int handle);                   \
    _Pragma( STRINGIFY( weak delete_ ## type ## _ = delete_ ## type) )
DEFINE_DELETE_OBJECT(foo);

quand mis en gcc -Edonne

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;
Scott Wales
la source
32
En tant que FYI: MSVC a l' __pragma()opérateur de préprocesseur, qui est malheureusement légèrement différent de l' _Pragma()opérateur de C99 (C99 prend une chaîne littérale, MSVC prend des jetons qui ne sont pas dans une chaîne): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Michael Burr
15
@MichaelBurr MSVC doit toujours être différent, n'est-ce pas?
Thomas
5

Une bonne chose que vous pouvez faire avec _Pragma ("argument") est de l'utiliser pour résoudre certains problèmes du compilateur tels que

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
John Thomas
la source
0

Non, il n'y a pas de moyen portable de faire cela. Là encore, il n'y a aucun moyen portable d'utiliser #pragma. Pour cette raison, de nombreux compilateurs C / C ++ définissent leurs propres méthodes pour faire des choses de type pragma, et ils peuvent souvent être intégrés dans des macros, mais vous avez besoin d'une définition de macro différente sur chaque compilateur. Si vous êtes prêt à suivre cette voie, vous finissez souvent par faire des choses comme celle-ci:

#if defined(COMPILER_GCC)
#define Weak_b
#define Weak_e __attribute__((weak))
#elif defined(COMPILER_FOO)
#define Weak_b __Is_Weak
#define Weak_e
#endif

#define DEFINE_DELETE_OBJECT(type)                      \
    Weak_b void delete_ ## type_(int handle) Weak_e;    \
    Weak_b void delete_ ## type(int handle)  Weak_e;    

Dans le cas où ce n'est pas évident, vous voulez définir Weak_bet Weak_ecomme constructions de bracketing de début et de fin parce que certains compilateurs comme GCC ajoutent les attributs comme un addendum à une signature de type, et certains, comme MSC, l'ajoutent comme préfixe (ou du moins il l'a fait une fois, cela fait des années que j'ai utilisé MSC). Avoir des structures de bracketing vous permet de définir quelque chose qui fonctionne toujours, même si vous devez passer la signature de type entière dans une construction de compilateur.

Bien sûr, si vous essayez de porter ceci à un compilateur sans les attributs que vous voulez, vous ne pouvez rien faire d'autre que de laisser les macros se développer à rien et espérer que votre code fonctionne toujours. En cas de pragmas purement d'avertissement ou d'optimisation, cela est probable. Dans d'autres cas, pas tellement.

Oh, et je suppose que vous auriez en fait besoin de définir Weak_b et Weak_e comme des macros qui prennent des paramètres, mais je n'étais pas disposé à lire la documentation pour savoir comment créer une définition faible juste pour cet exemple. Je laisse cela comme un exercice pour le lecteur.

swestrup
la source
-3

existe-t-il un moyen d'intégrer une instruction pragma dans une macro avec d'autres instructions?

Non, vous ne pouvez pas placer d'instructions de préprocesseur dans des instructions de préprocesseur. Vous pouvez cependant le mettre dans une inlinefonction. Cela bat le Ctag, cependant.

sbi
la source
1
À quoi cela servirait-il de le mettre dans une fonction en ligne? Les directives du préprocesseur sont traitées avant tout ce qui pourrait reconnaître une fonction.
2
C99 a inline, et la plupart des implémentations majeures de C89 ont quelques variations.
Chris Lutz
@Chris En supposant que votre commentaire s'adresse à moi - votre point est - quoi?
@Neil - Non, désolé. Je le dirigeais vers la dernière phrase de @ sbi.
Chris Lutz
1
@Chris: Ah, il en inlineva de même pour une autre chose que C a empruntée à C ++! :)
sbi