Nein kann dies nicht der Fall sein, denn nicht jeder inovocation von constexpr Funktion in der Lage sein zu bewerten hat als Teilausdruck eines Kernkonstantenausdrucks. Wir benötigen nur einen Argumentwert, der dies ermöglicht. Eine conexpr-Funktion kann also eine throw-Anweisung enthalten, solange wir einen Argumentwert haben, der diesen Zweig nicht aufruft.
Dies wird in dem Entwurf ++ 14 Standard-Teil C abgedeckt 7.1.5
Der constexpr Spezifizierer [dcl.constexpr], die uns sagt, was in einer constexpr Funktion erlaubt ist:
Die Definition einer constexpr Funktion erfüllen soll die folgenden Randbedingungen:
es soll nicht virtuell sein (10.3);
Der Rückgabetyp muss ein Literaltyp sein;
jeder seiner Parametertypen muss ein Literaltyp sein;
seine Funktion Körper wird sein = löschen = default oder eine Verbindung-Anweisung, die nicht
die, wie wir nicht throw
und in der Tat wenig verbietet sehr sehen verbietet, da der Relaxing constraints on constexpr functions Vorschlag Teil von C++ 14 wurde.
Im Folgenden finden Sie in der Regel, dass eine constexpr Funktion sagt wohlgeformt ist, wenn mindestens ein Argument Wert existiert, so dass er als Unterausdruck eines Kern konstanten Ausdruck ausgewertet werden kann:
Für eine nicht Vorlage, nicht standardmäßige consExpr-Funktion oder Nicht-Vorlage, nicht-voreingestellt, nicht ererbend consExpr-Konstruktor, Wenn keine Argumentwerte vorhanden sind, kann ein Aufruf der Funktion oder des Konstruktors ein ausgewerteter Unterausdruck eines konstanten Kernausdrucks sein (5.19), das Programm ist schlecht gebildet; nein Diagnose erforderlich.
und unterhalb dieses Absatzes wir das folgende Beispiel haben, die für diesen Fall ein perfektes Beispiel zeigt:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
So würden wir die Ausgabe für das folgende Beispiel erwarten:
#include <iostream>
constexpr int f(bool b) { return b ? throw 0 : 0; }
int main() {
std::cout << noexcept(f(1)) << "\n"
<< noexcept(f(0)) << "\n" ;
}
sein (see it live with gcc):
0
1
Visual Studio über webcompiler erzeugt auch das gleiche Ergebnis. Wie bereits erwähnt, hat clang einen Fehler, wie in dem Fehlerbericht noexcept should check whether the expression is a constant expression dokumentiert.
Defect Bericht 1129
Defect report 1129: Default nothrow for constexpr functions fragt die gleiche Frage:
A constexpr Funktion ist nicht erlaubt, über eine Ausnahme zurückzukehren.Dies sollte erkannt werden, und eine Funktion, die als consExpr ohne eine explizite Ausnahmebestimmung deklariert wird, sollte so behandelt werden, als wäre sie nicht als exception (true) deklariert und nicht als die übliche noexcept (false). Für eine Funktionsvorlage, die mit consExpr ohne explizite Ausnahmespezifikation deklariert wurde, sollte sie nur dann als exception (true) betrachtet werden, wenn das Schlüsselwort constexpr bei einer bestimmten Instantiierung eingehalten wird.
und die Antwort war:
Die Prämisse ist nicht korrekt: eine Ausnahme nur verboten, wenn eine constexpr Funktion in einem Kontext aufgerufen wird, die einen konstanten Ausdruck erfordert. Als gewöhnliche Funktion verwendet, kann es werfen.
und modifizierte 5.3.7 [expr.unary.noexcept] Absatz 3 Punkt 1 (Zusätzlich stellte mit Schwerpunkt):
eine potenziell ausgewertet call80 auf eine Funktion, Member-Funktion, Funktion Zeiger oder Pointer-Elementfunktion, die keine nicht-Wurf exception-Spezifikation hat (15.4 [except.spec]), , wenn der Anruf ein konstanter Ausdruck ist (5,20 [expr.const]),
@ cad sowieso t Die Frage ist sehr allgemein, denke nicht, dass es ein gutes spezifisches Beispiel gibt. – Orient
Gegenbeispiel: 'constexpr void * foo (int n) {return n == 0? nullptr: operator neu (n); } '. [Demo] (https://ideone.com/zlTsDI). –
Ich habe dies einmal missbraucht, siehe http://stackoverflow.com/a/13305072/34509 –