2010-06-12 7 views
76

C'è un modo per incorporare l'istruzione pragma in macro con altre istruzioni?Pragma in define macro

che sto cercando di realizzare qualcosa di simile:

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

sto bene con le soluzioni Boost (salvo a microonde), se ne esiste uno.

+5

Probabilmente non è né - #pragmas non sono definiti dagli standard C o C++. –

+0

Il preprocessore è, anche se lo specifico sottocomando consentito che vuole eseguire non lo è. – Puppy

+0

@DeadMG: Esistono molte cose comuni tra C e C++. Sebbene la pre-elaborazione sia prevalentemente comune, ci sono grandi differenze nel modo in cui viene specificata la pre-elaborazione, a seconda dello standard di linguaggio utilizzato (C89, C99, C++ e FCD C++ 0x). –

risposta

94

Se si utilizza C99 o C++ 0x c'è l'operatore pragma, utilizzato come

_Pragma("argument") 

che equivale a

#pragma argument 

tranne che può essere utilizzato nelle macro (vedi sezione 6.10.9 dello standard C99, o 16,9 del C++ 0x progetto comitato definitivo)

Per esempio,

#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); 

quando sia messo in gcc -E

void delete_foo_(int handle); void delete_foo(int handle); 
#pragma weak delete_foo_ = delete_foo 
; 
+29

FYI: MSVC ha l'operatore di preprocessore '__pragma()', che sfortunatamente è leggermente diverso dall'operatore '_Pragma()' di C99 (C99 prende una stringa letterale, MSVC prende token che non sono in una stringa): http://msdn.microsoft.com/en-us/library/d9x1s805.aspx –

+10

@MichaelBurr MSVC deve sempre essere diverso, non è vero? – Thomas

-3

c'è un modo per incorporare l'istruzione pragma in macro con altre istruzioni?

No, non è possibile inserire istruzioni di preprocessore in istruzioni di preprocessore. Tuttavia, è possibile inserirlo in una funzione inline. Ciò sconfigge però il tag C.

+1

A cosa serve fare una funzione inline? Le direttive del preprocessore vengono elaborate prima di tutto ciò che potrebbe riconoscere una funzione. –

+2

C99 ha 'inline' e la maggior parte delle implementazioni C89 ha qualche variazione. –

+0

@Chris Supponendo che il tuo commento fosse diretto contro di me - il tuo punto è - cosa? –

0

No, non esiste un modo portatile per farlo. Poi di nuovo, non ci sono modi portatili per usare #pragma. Per questo motivo, molti compilatori C/C++ definiscono i propri metodi per fare cose pragma-like, e spesso possono essere incorporati in macro, ma è necessaria una diversa definizione di macro su ogni compilatore. Se siete disposti a seguire questa strada, spesso si finisce per fare cose come questa:

#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;  

Nel caso in cui il suo non è ovvio che si desidera definire Weak_b e Weak_e come costrutti bracketing inizio-e-end perché alcuni compilatori come GCC aggiungi gli attributi come appendice a una firma di tipo e alcuni, come MSC, aggiungono come prefisso (o almeno lo ha fatto una volta, sono passati anni da quando ho usato MSC). Avere contrasti di bracketing consente di definire qualcosa che funziona sempre, anche se si deve passare l'intera firma di tipo in un costrutto del compilatore.

Ovviamente, se si prova a eseguire il porting su un compilatore senza gli attributi desiderati, non c'è nulla che si possa fare, ma lasciare le macro espandersi su nulla e sperare che il codice funzioni ancora. In caso di pragmi puramente di avvertimento o di ottimizzazione, è probabile. In altri casi, non così tanto.

Oh, e sospetto che sia effettivamente necessario definire Weak_b e Weak_e come macro che accettano parametri, ma non ero disposto a leggere i documenti per come creare una definizione debole solo per questo esempio. Lo lascio come esercizio per il lettore.

4

Una cosa bella che puoi fare con _Pragma ("argomento") è usarlo per affrontare alcuni problemi di compilazione, come

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