Pragma w definiowaniu makra

99

Czy istnieje sposób osadzenia instrukcji pragmy w makrze z innymi instrukcjami?

Próbuję osiągnąć coś takiego:

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

Nie ma problemu z rozwiązaniami doładowania (z wyjątkiem fali), jeśli takie istnieją.

Anycorn
źródło
5
Prawdopodobnie tak nie jest - #pragi nie są zdefiniowane ani przez standardy C, ani C ++.
Preprocesorem jest, nawet jeśli konkretna dozwolona komenda, którą chce uruchomić, nie jest.
Puppy
@DeadMG: Jest wiele rzeczy wspólnych między C i C ++. Podczas gdy przetwarzanie wstępne jest przeważnie powszechne, istnieją poważne różnice w sposobie określania przetwarzania wstępnego w zależności od używanego standardu językowego (C89, C99, C ++ i C ++ 0x FCD).
James McNellis,
2
@James McNellis: Tylko dlatego, że z technicznego punktu widzenia większość programów w C jest przenośna do C ++, nie czyni tej prawdziwie powszechnej funkcjonalności, ponieważ żaden programista C ++ nie zrobiłby jej większości. Te dwa języki tak naprawdę nie mają ze sobą wiele wspólnego.
Puppy

Odpowiedzi:

116

Jeśli używasz c99 lub c ++ 0x, istnieje operator pragma, używany jako

_Pragma("argument")

co jest równoważne z

#pragma argument

z wyjątkiem tego, że może być używany w makrach (patrz sekcja 6.10.9 standardu c99 lub 16.9 ostatecznej wersji roboczej komisji c ++ 0x)

Na przykład,

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

po umieszczeniu w gcc -Edaje

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;
Scott Wales
źródło
32
Jako FYI: MSVC ma __pragma()operatora preprocesora, który niestety różni się nieco od _Pragma()operatora C99 (C99 przyjmuje literał ciągu, MSVC pobiera tokeny, które nie są w ciągu): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Michael Burr
15
@MichaelBurr MSVC zawsze musi być inny, prawda?
Thomas
5

Jedną fajną rzeczą, którą możesz zrobić z _Pragma ("argument"), jest użycie go do rozwiązywania niektórych problemów z kompilatorem, takich jak

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif
John Thomas
źródło
0

Nie, nie ma na to przenośnego sposobu. Z drugiej strony, w ogóle nie ma przenośnych sposobów używania #pragma. Z tego powodu wiele kompilatorów C / C ++ definiuje własne metody robienia rzeczy podobnych do pragmy i często można je osadzać w makrach, ale potrzebujesz innej definicji makra na każdym kompilatorze. Jeśli chcesz iść tą drogą, często kończysz na takich rzeczach:

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

W przypadku, gdy nie jest to oczywiste, chcesz zdefiniować Weak_bi Weak_ejako konstrukcje nawiasów rozpoczynających i kończących, ponieważ niektóre kompilatory, takie jak GCC, dodają atrybuty jako uzupełnienie do podpisu typu, a niektóre, jak MSC, dodają go jako przedrostek (a przynajmniej tak kiedyś minęły lata, odkąd używałem MSC). Posiadanie konstrukcji w nawiasach pozwala zdefiniować coś, co zawsze działa, nawet jeśli musisz przekazać całą sygnaturę typu do konstrukcji kompilatora.

Oczywiście, jeśli spróbujesz przenieść to do kompilatora bez wymaganych atrybutów, nie możesz nic zrobić, ale pozostawić makra rozwinięte do niczego i mieć nadzieję, że twój kod nadal działa. Jest to prawdopodobne w przypadku pragm czysto ostrzegawczych lub optymalizujących. W innych przypadkach nie tak bardzo.

Aha, i podejrzewam, że faktycznie musiałbyś zdefiniować Weak_b i Weak_e jako makra, które przyjmują parametry, ale nie chciałem czytać dokumentacji, aby dowiedzieć się, jak utworzyć słabą definicję tylko dla tego przykładu. Zostawiam to jako ćwiczenie dla czytelnika.

swestrup
źródło
-3

czy istnieje sposób na osadzenie instrukcji pragma w makrze z innymi instrukcjami?

Nie, nie można umieścić instrukcji preprocesora w instrukcjach preprocesora. Mógłbyś jednak umieścić go w inlinefunkcji. To jednak pokonuje Cmetkę.

sbi
źródło
1
Co dobrego przyniosłoby umieszczenie go w funkcji inline? Dyrektywy preprocesora są przetwarzane przed wszystkim, co mogłoby rozpoznać funkcję.
2
C99 ma inline, a większość głównych implementacji C89 ma pewne odmiany.
Chris Lutz,
@Chris Zakładając, że Twój komentarz był skierowany do mnie - chodzi ci o - co?
@Neil - Nie, przepraszam. Reżyserowałem to w ostatnim zdaniu @ sbi.
Chris Lutz,
1
@Chris: Ach, inlinekolejna rzecz, którą C pożyczył z C ++! :)
sbi