2013-02-16 6 views
6

In C++ 11, wenn eine Vorverarbeitung Richtlinie von der Form ...Bedingte Aufnahme in C++ 11 mit benutzerdefiniertem Literal?

#if expr 

... angetroffen wird, wird expr als constant-expression bewertet wie in 16.1 [cpp.cond] beschrieben.

Dieser nach Makro Ersatz auf expr gemacht wird, seine Kennungen (und Schlüsselwörter) durch 0 ersetzt werden, werden ihre preprocessing-tokens zu tokens, umgewandelt defined Operator ausgewertet wird, und so weiter.

Meine Frage ist, was passiert, wenn einer der Token in expr ein user-defined-literal ist?

Benutzerdefinierte Literale sind wie Funktionsaufrufe, aber Funktionsaufrufe können nicht auftreten in expr (glaube ich), als Nebeneffekt der Identifier Ersetzung. Jedoch technisch user-defined-literals könnte überleben.

Ich vermute, dass es ein Fehler ist, aber ich kann nicht ganz sehen, wie man das vom Standard schließt?

Vielleicht wurde die (pedantische) Auswirkung des Hinzufügens von benutzerdefinierten Literalen auf Klausel 16 [cpp] einfach ignoriert?

Oder fehlt mir etwas?

Update:

durch ein Beispiel zu verdeutlichen:

Was bedeutet das Vorprozess an:

#if 123_foo + 5.5 > 100 
bar 
#else 
baz 
#endif 

bar oder baz oder ist es ein Fehler?

GCC 4.7 Berichte:

test.cpp:1:5: error: user-defined literal in preprocessor expression 

so denkt, dass es es ein Fehler ist. Kann dies mit Bezug auf den Standard begründet werden? Oder ist das nur "implizit"?

+0

Die Vorstellung des Präprozessors von "konstantem Ausdruck" ist ganz anders als die von C++, glaube ich. Sie können wirklich nur Literale und Makros verwenden, die schließlich zu Literalen expandieren ... zumindest habe ich das immer verstanden. –

+0

Sieht so aus, als ob deine Version von g ++ etwas vermisst, nicht du. –

+1

Ich bezweifle, dass es die Absicht des Komitees war, so etwas zuzulassen, da die Logik der Vorverarbeitung und der Sprachsemantik schon immer so getrennt waren. Aber ja, der Standard scheint zu implizieren, dass er behandelt werden sollte. – aschepler

Antwort

3

in C++ 11, wenn eine Vorverarbeitung Richtlinie von der Form ... #if expr ... angetroffen wird, wird expr als constant-expression bewertet wie in 16.1 [cpp.cond] beschrieben.

nach Makro Ersatz getan Dies wird auf expr sind seine Kennungen (und Schlüsselwörter) durch 0 ersetzt, seine preprocessing-tokens zu tokens umgewandelt werden, defined Operator ausgewertet wird, und so weiter.

Meine Frage ist, was passiert, wenn einer der tokens in expr ist ein user-defined-literal?

Das Programm ist schlecht formatiert.

Der Kern meiner Argumentation ist in 16.1/1 Fußnote 147, dass in der Übersetzung Phase 4 dort aus der Beobachtung gewonnenen noch keine identifiers andere als Makronamen sind.

Argument:

Nach 2.14.8 [lex.ext]/2

A user-defined-literal wird als Aufruf an einen literal operator oder literal operator template(13.5.8) behandelt.

Also hier haben wir einen verbleibenden Aufruf an eine (Operator) -Funktion auch nach allen Substitutionen beschrieben in 16.1/4. (Andere Versuche, beispielsweise eine constexpr Funktion zu nutzen, würde durch die Substitution aller nicht-Makro identifiers durch 0 vereitelt werden.)

Wenn dies geschieht in Übersetzungsphase 4 sind keine definiert oder sogar Funktionen deklariert noch; ein Versuch der Suche nach der literal-operator-id muss fehlschlagen (siehe Fußnote 147 in 16.1/1 für ein ähnliches Argument).

Von einem etwas anderen Winkel, bei 5.19/2 suchen wir finden:

A conditional-expression ein core constant expression ist, es sei denn es eine der folgenden als potenziell bewertet subexpression (3.2) beinhaltet [...]:

  • [...]]
  • ein Aufruf einer anderen Funktion als eines consExpr-Konstruktors für eine Literalklasse oder eine constexpr-Funktion;
  • ein Aufruf einer undefinierten consExpr-Funktion oder eines undefinierten conexpr-Konstruktors [...];

Daraus Verwendung eines user-defined literal in einem constant expression erfordert eine definiert und constexprliteral operator, die wiederum nicht 4.

gcc rechts in Übersetzungsphase zur Verfügung stehen kann, ist abzulehnen Dies.

0

In C++ 11, wenn eine Vorverarbeitung Richtlinie des Formulars #ifdef expr angetroffen wird, expr als Konstantausdruck wie beschrieben 16.1 bewertet. Dies geschieht nach dem Makroaustausch auf Ausdruck, seine Kennungen (und Schlüsselwörter) werden durch 0 ersetzt, seine Vorverarbeitungstoken werden in Token konvertiert, der definierte Operator wird ausgewertet und so weiter.

Nein!

Das Argument #ifdef, #ifndef oder defined ist nicht ausgewertet. Nehmen wir zum Beispiel an, dass ich niemals das Präprozessorsymbol #defineSYMBOL_THAT_IS_NEVER_DEFINED. Dies ist absolut gültig:

#ifdef SYMBOL_THAT_IS_NEVER_DEFINED 
code 
#endif 

Das Erweitern eines Symbols, das nicht definiert ist, ist illegal.Dies ist illegal SYMBOL_THAT_IS_NEVER_DEFINED Annahme nicht definiert wurde:

#if SYMBOL_THAT_IS_NEVER_DEFINED 
code 
#endif 

Analog zur Überprüfung, ob ein Zeiger nicht null ist, bevor dereferencing es, zu prüfen, ob ein Symbol definiert ist es vor der Verwendung ist legal:

#if (defined SYMBOL_THAT_MIGHT_BE_DEFINED) && SYMBOL_THAT_MIGHT_BE_DEFINED 
code 
#endif 
+0

Leider habe ich einen Tippfehler in der Frage gemacht, ich meinte '# expr', nicht' #ifdef expr'. Ich habe die Frage korrigiert, bitte passen Sie Ihre Antwort entsprechend an. –

+0

Beachten Sie auch, dass 'expr' in meiner Frage eine ganze Reihe von Token darstellt, die einem' constant-expression' entsprechen - und nicht dem einzelnen Bezeichner 'expr'. –

+0

Siehe "Update" in Frage –