web-dev-qa-db-fra.com

Pragma dans la macro de définition

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

J'essaie 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 une.

91
Anycorn

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 des macros (voir la section 6.10.9 de la norme c99, ou 16.9 de l'ébauche finale 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);

lorsqu'il est placé dans gcc -E donne

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;
105
Scott Wales

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

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
4
John Thomas

Non, il n'y a aucun moyen portable de le faire. 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 incorporés dans des macros, mais vous avez besoin d'une définition de macro différente sur chaque compilateur. Si vous êtes prêt à emprunter cette voie, vous finissez souvent par faire des choses comme ça:

#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_b et Weak_e en tant que constructions de bracketing de début et de fin, car certains compilateurs comme GCC ajoutent les attributs comme addenda à une signature de type, et certains, comme MSC l'ajoutent en tant que préfixe (ou du moins l'a fait une fois, cela fait des années que je n'ai pas utilisé MSC.) Le fait d'avoir des structures entre crochets 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 cela sur un compilateur sans les attributs que vous voulez, vous ne pouvez rien faire, mais laisser les macros se développer à rien et espérer que votre code fonctionne toujours. En cas d'avertissement pur ou d'optimisation de pragmas, cela est probable. Dans d'autres cas, pas tant que ça.

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

0
swestrup