Was Sie suchen ist § 5.19:
A bedingungsausdrucke ein Kern konstanter Ausdruck, es sei denn die Bewertung der e ist nach den Regeln der abstrakten Maschine (1.9), wäre eine der folgenden Ausdrücke bewerten:
Dies gilt für die Auswertung eines Ausdrucks, der ein constexpr
Funktionsaufruf ist. Das heißt, das Aufrufen einer constexpr
-Funktion wird ein "konstanter Kernausdruck" sein, wenn das Auswerten der Funktion, dh das Ausführen des Rumpfs der Funktion gemäß den Regeln der abstrakten C++ - Maschine, keines der in der Liste verbotenen Dinge tut in § 5.19.
Eines der Elemente in der Liste ist:
- ein Aufruf einer anderen Funktion als [...] eine constexpr Funktion
So dies zu Ihrem Beispiel anwenden : Auswerten des Ausdrucks foo()
wertet einen Aufruf für eine Funktion incr()
aus, die keine constexpr-Funktion ist, was bedeutet, dass der Ausdruck foo()
kein Ausdruck für die Kernkonstante ist.
Weiter, da das oben für alle möglichen Aufrufe Ihrer Funktion foo
gilt, tritt die Regel in § 7.1.5/5 in Kraft und bedeutet, dass Ihr Beispielprogramm schlecht ausgebildet ist, keine Diagnose erforderlich, auch wenn Sie nie rufen Sie tatsächlich foo()
.
Wie Ben Voigt weist eine constexpr Funktion aus können Anrufe an Nicht-consexpr Funktionen enthalten, solange die besondere Auswertung der Funktion wertet nicht tatsächlich eine solche Funktionsaufruf (oder scheint es in einem Kontext, der tut nicht einen konstanten Ausdruck erfordern).
Die Einschränkungen in 5.19 beziehen sich nur darauf, welche Ausdrücke tatsächlich als Teil der Auswertung eines Ausdrucks ausgewertet werden.
Zum Beispiel:
#include <iostream>
int incr(int &n) { return ++n; }
enum E {be_constexpr, not_constexpr};
constexpr int foo(E e = be_constexpr) {
int n = 0;
if (e == not_constexpr) { incr(n); }
return n;
}
int main() {
constexpr int a = foo(); // foo() is a constant expression
int b = foo(not_constexpr); // may or may not evaluate `foo(non_constexpr)` at runtime. In practice modern C++ compilers will do compile-time evaluation here even though they aren't required to.
// constexpr int c = foo(not_constexpr); // Compile error because foo(not_constexpr) is not formally a constant expression, even though modern compilers can evaluate it at compile-time.
std::cout << a << ' ' << b << '\n';
}
Wahrscheinlich erwähnenswert, die [vorherige Frage] (http://stackoverflow.com/q/34211688/1708801), die eine Menge von dem gleichen Boden bedeckt, obwohl aus einer anderen Perspektive . –
@ShafikYaghmour Ich würde mich sehr über Ihre Kommentare zu dieser neuen Frage freuen. – Ayrosa
Beachten Sie, dass die Dinge, die Sie zitiert haben, sind * notwendig *, aber nicht * ausreichend * Bedingungen, dh wenn diese Bedingungen verletzt werden dann ist der Code schlecht gebildet, aber wenn sie nicht verletzt werden, dann kann der Code richtig sein und wir muss auf andere Teile der Spezifikation schauen. –