Pragma im Makro definieren

99

Gibt es eine Möglichkeit, Pragma-Anweisungen mit anderen Anweisungen in Makros einzubetten?

Ich versuche etwas zu erreichen wie:

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

Ich bin mit Boost-Lösungen (außer Wave) einverstanden, wenn es eine gibt.

Anycorn
quelle
5
Wahrscheinlich ist es auch nicht - #pragmas werden weder durch die C- noch durch die C ++ - Standards definiert.
Der Präprozessor ist, auch wenn der spezifische zulässige Unterbefehl, den er ausführen möchte, nicht vorhanden ist.
Welpe
@DeadMG: Es gibt sehr viele Dinge, die zwischen C und C ++ gemeinsam sind. Während die Vorverarbeitung meistens üblich ist, gibt es große Unterschiede in der Spezifikation der Vorverarbeitung, je nachdem, welcher Sprachstandard verwendet wird (C89, C99, C ++ und C ++ 0x FCD).
James McNellis
2
@ James McNellis: Nur weil die meisten C-Programme technisch auf C ++ portierbar sind, ist diese wirklich übliche Funktionalität nicht verfügbar, da kein C ++ - Programmierer die überwiegende Mehrheit davon ausführen würde. Die beiden Sprachen haben eigentlich nicht viel gemeinsam.
Welpe

Antworten:

114

Wenn Sie c99 oder c ++ 0x verwenden, gibt es den Pragma-Operator, der als verwendet wird

_Pragma("argument")

das ist äquivalent zu

#pragma argument

außer es kann in Makros verwendet werden (siehe Abschnitt 6.10.9 des c99-Standards oder 16.9 des endgültigen Ausschussentwurfs von c ++ 0x)

Beispielsweise,

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

wenn in gcc -Egibt

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;
Scott Wales
quelle
32
Zu Ihrer Information: MSVC verfügt über den __pragma()Präprozessor-Operator, der sich leider geringfügig vom _Pragma()Operator von C99 unterscheidet (C99 verwendet ein Zeichenfolgenliteral, MSVCs verwendet Token, die nicht in einer Zeichenfolge enthalten sind): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Michael Burr
15
@MichaelBurr MSVC muss immer anders sein, nicht wahr?
Thomas
5

Eine nette Sache, die Sie mit _Pragma ("Argument") tun können, ist es, um einige Compilerprobleme wie z

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

Nein, dafür gibt es keine tragbare Möglichkeit. Andererseits gibt es überhaupt keine tragbaren Möglichkeiten, #pragma zu verwenden. Aus diesem Grund definieren viele C / C ++ - Compiler ihre eigenen Methoden, um pragmaähnliche Dinge auszuführen, und sie können häufig in Makros eingebettet werden. Sie benötigen jedoch für jeden Compiler eine andere Makrodefinition. Wenn Sie bereit sind, diesen Weg zu gehen, machen Sie oft solche Dinge:

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

Für den Fall , es ist nicht klar , wollen Sie definieren Weak_bund Weak_ewie beginnen-und-End - Konstrukte Bracketing weil einige Compiler wie GCC die Attribute als Zusatz zu einer Art Signatur hinzuzufügen, und einige, wie MSC fügen Sie es als Präfix (oder zumindest tat es Es ist Jahre her, seit ich MSC verwendet habe. Mit Klammerkonstruktionen können Sie etwas definieren, das immer funktioniert, auch wenn Sie die gesamte Typensignatur an ein Compilerkonstrukt übergeben müssen.

Wenn Sie versuchen, dies auf einen Compiler ohne die gewünschten Attribute zu portieren, können Sie natürlich nichts anderes tun, als die Makros auf nichts erweitern zu lassen und hoffen, dass Ihr Code weiterhin ausgeführt wird. Im Falle einer reinen Warnung oder Optimierung von Pragmas ist dies wahrscheinlich. In anderen Fällen nicht so sehr.

Oh, und ich vermute, Sie müssten Weak_b und Weak_e tatsächlich als Makros definieren, die Parameter annehmen, aber ich war nicht bereit, die Dokumente zu lesen, um eine schwache Definition nur für dieses Beispiel zu erstellen. Ich überlasse das dem Leser als Übung.

swestrup
quelle
-3

Gibt es eine Möglichkeit, Pragma-Anweisungen mit anderen Anweisungen in Makros einzubetten?

Nein, Sie können Präprozessoranweisungen nicht in Präprozessoranweisungen einfügen. Sie können es jedoch in eine inlineFunktion einfügen. Das besiegt das CTag jedoch.

sbi
quelle
1
Was würde es nützen, es in eine Inline-Funktion zu integrieren? Präprozessoranweisungen werden vor allem verarbeitet, was eine Funktion erkennen könnte.
2
C99 hat inlineund die meisten großen C89-Implementierungen haben einige Variationen.
Chris Lutz
@ Chris Angenommen, Ihr Kommentar war an mich gerichtet - Ihr Punkt ist - was?
@Neil - Nein, sorry. Ich habe es auf @ sbis letzten Satz gerichtet.
Chris Lutz
1
@ Chris: Ah, so inlineist noch eine andere Sache, die C von C ++ entlehnt hat! :)
sbi