2015-04-03 4 views
25

Ich habe Probleme mit constexpr. Das Buch C++ Primer zeigt eine Codezeile:Verwendung der constexpr-Funktion, bevor die Definition fehlschlägt

constexpr int sz = size(); // only size() is a constexpr function 
          // this code is right 

jedoch das Buch nicht ein spezielles Beispiel nicht geben. Also versuche ich den folgenden Code von mir:

#include <iostream> 
constexpr int fun(); 
int main() 
{ 
    constexpr int f = fun(); 
    std::cout << f << std::endl; 
} 
constexpr int fun() 
{ 
    return 3; 
} 

Aber mein Compiler sagte fun() nicht definiert ist.

Wenn ich constexpr in const ändern, es funktioniert gut, und wenn ich den Code ändern die constexpr Funktion vor der Verwendung zu definieren:

#include <iostream> 
constexpr int fun() 
{ 
    return 3; 
} 
int main() 
{ 
    constexpr int f = fun(); 
    std::cout << f << std::endl; 
} 

Es funktioniert auch gut. Kann mir jemand sagen warum?

+1

Welchen Compiler benutzen Sie? – kvorobiev

+0

@kvorobiev clang, linux – icecity96

+0

Welche Version von clang? – kvorobiev

Antwort

15

Eine constexpr-Funktion muss NICHT vor der ersten Verwendung definiert werden. Das Ergebnis eines vor der Definition durchgeführten Aufrufs ist jedoch kein konstanter Ausdruck.

Quelle: C++ Standard-Entwurf n4296, Abschnitt 5.20:

A bedingungsausdrucke ist ein Kern konstanter Ausdruck es sei denn, die Bewertung von e, die Regeln der abstrakten Maschine folgen, würde bewerten eine der folgenden Ausdrücke:

  • this, außer in einer constexpr Funktion oder ein constexpr co nstructor, der als Teil von e ausgewertet wird;
  • ein Aufruf einer anderen Funktion als eines constexpr Konstruktors für eine Literalklasse, eine constexpr Funktion oder ein impliziter Aufruf eines trivialen Destruktors [Anmerkung: Überladungsauflösung wird angewendet wie üblich - Endnote];
  • ein Aufruf einer undefinierten constexpr Funktion oder ein undefinierter constexpr Konstruktor;
  • ...

Version von Entwurf 3485 (Abschnitt 5.19):

A bedingungsausdruck ist ein Kern konstanter Ausdruck es sei denn, es ist eines der folgenden umfasst als ein möglicherweise ausgewerteter Teilausdruck, aber Teilausdrücke von logischen UND-, logischen ODER- und bedingten Operationen, die nicht ausgewertet werden, werden nicht berücksichtigt [Hinweis: Ein überladener Operator ruft eine Funktion auf.- Endnote]:

  • this [Anmerkung: Wenn ein konstanter Ausdruck Auswertung Funktionsaufruf Substitution ersetzt jedes Auftreten von this in einer constexpr Elementfunktion mit einem Zeiger auf das Klassenobjekt. - Endnote];
  • ein Aufruf einer anderen Funktion als eines constexpr Konstruktors für eine Literalklasse oder eine constexpr Funktion [Hinweis: Überladungsauflösung wird wie üblich angewendet - Endnote];
  • ein Aufruf einer undefinierten constexpr Funktion oder ein undefinierter constexpr Konstruktor
  • ...

Das Beispiel int x2 = s. t(); in n2235 wurde tatsächlich gültig aufgrund der vor der Standardisierung vorgenommenen Änderungen. constexpr int x2 = s. t(); bleibt jedoch ein Fehler.

+0

n4296 ist ein Entwurf C++ Standart. Haben Compiler das bereits unterstützt? – kvorobiev

+1

@kvorobiev: Ich zitiere aus einem Entwurf, weil es öffentlich ist. Die Regel wurde früher einige Entwürfe eingeführt und ist Teil des offiziellen Standards. –

+0

@ kvorobiev können Sie N3337 5.19/2 betrachten, die im Grunde die endgültige Version des C++ 11-Standards ist. g ++/clang ++ sind C++ 11-konform (mit kleinen Ausnahmen) – vsoftco

3

Eine Funktion für einen konstanten Ausdruck muss vor der ersten Verwendung definiert werden. Siehe hierzu paper, Ende von Abschnitt 4.1.

+0

Also dann ist das Buch fehlerhaft? Vielleicht akzeptieren einige Compiler diese Syntax, obwohl sie vom Standard nicht erlaubt sind? –

+0

Nach dieser [Tabelle] (http://wiki.apache.org/stdcxx/C++0xCompilerSupport) unterstützen einige Compiler jetzt constexpr und ich bezweifle, dass einer von ihnen diese Syntax unterstützt. – kvorobiev

+0

@kvorobiev, aber die wichtigsten Compiler sind ziemlich C++ 11-bereit, insbesondere g ++/clang ++. MSVC noch nicht, aber dahin. – vsoftco

Verwandte Themen