2010-11-26 11 views
13

Mein mentales Modell, wie der Präprozessor funktioniert, ist anscheinend unvollständig, und das macht mich verrückt.Präprozessor Token Erweiterung

Ich möchte zwei Tokens verketten, aber das zweite Token sollte zuerst erweitert werden.

#define ANSWER 42 

#define FOO foo_ ## ANSWER 

Hier erweitert FOO-foo_ANSWER, aber ich will es foo_42 sein. So definiere ich einen MERGE Makro in der Hoffnung, dass dies irgendwie die Argumente vor Verkettung erweitern würde:

#define MERGE(x, y) x ## y 

#define BAR MERGE(bar_, ANSWER) 

Aber BAR noch bar_ANSWER erweitert statt bar_42. So definiere ich ein anderes Makro HELPER:

#define HELPER(x, y) MERGE(x, y) 

#define BAZ HELPER(baz_, ANSWER) 

Und jetzt BAZ erfolgreich zu baz_42 erweitert. Im Moment scheint das für mich wie Magie zu sein.

Kann mir jemand dieses Verhalten erklären? Wie funktionieren die Erweiterungsregeln genau?

+0

Es tut mir leid zu sagen, dass ich auch eine mögliche doppelte Frage des gleichen Problems gemacht hatte. Ich frage mich, warum dieses Verhalten nicht eindeutig dokumentiert ist. Ich meine den Algorithmus, den Präprozessor betreibt. –

+0

@sandundhammika: Es ist ziemlich genau in der Spezifikation dokumentiert - Abschnitt 6.10.3 - obwohl es eine Reihe von undefinierten Verhaltensecken gibt. –

Antwort

7

Lesen Sie die Antwort auf Ihre Frage here:

Das Problem ist, dass, wenn Sie einen Makro Ersatz haben, den Präprozessor nur rekursiv, wenn weder der Zeichenfolgen Operator # noch das Token die Makros erweitern -Pasting Operator ## werden angewendet. Also, du zusätzliche Schichten von indirection verwenden müssen, können Sie verwenden, um die Token-Einfügen-Operator mit einem rekursiv erweitert Argument

+0

Und deshalb gibt es 'BOOST_PP_CAT' :) –

+0

Das obige Zitat ist nicht korrekt oder zumindest nicht vollständig. Um das Makro zu erweitern, benötigen Sie zwei Ebenen der Indirektion (getestet in VS2017, und Berichte derselben in Gnu cpp). Ich würde gerne eine Erklärung hören, warum die zweite Stufe der Indirektion notwendig ist. Nur eine Ebenenumleitung ohne "#" oder "##" zu haben, erweitert das Makro nicht. Aber die 2. Ebene tut es. –

3

Token Verkettung keine Makros erweitern, wenn Verkettung durchführen [ref].

Um dies zu umgehen, verwenden Sie eine Ebene der Indirektion und erhalten den Präprozessor, die Makros vor der Verkettung zu erweitern.

#define STEP1(x, y) STEP2(x, y) // x and y will be expanded before the call to STEP2 
#define STEP2(x, y) x ## y   // x and y will not be expanded, just pasted