Wann ist ein constexpr Funktion zur Kompilierzeit ausgewertet?
Da es möglich ist, dass eine Funktion deklariert als constexpr aufgerufen werden können, während der Laufzeit, unter welche Kriterien muss der compiler entscheiden, ob, um zu berechnen, es zur compile-Zeit oder zur Laufzeit?
template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
return (expo != 0 )? base * POW(base, expo -1) : 1;
}
int main(int argc, char** argv)
{
int i = 0;
std::cin >> i;
std::cout << POW(i, 2) << std::endl;
return 0;
}
In diesem Fall, ich, unbekannt ist zur compile-Zeit, das ist wahrscheinlich der Grund, warum der compiler behandelt POW() als normale Funktion, die aufgerufen wird, zur Laufzeit. Diese Dynamik jedoch, so bequem wie es zu sein scheint, hat etwas unpraktisch Auswirkungen. Zum Beispiel könnte es einen Fall, wo ich möchte, dass der compiler zur Berechnung eines constexpr Funktion während der compile-Zeit, wo der compiler entscheidet, Sie zu behandeln wie eine normale Funktion statt, wenn es funktioniert hätte, während der compile-Zeit als auch? Gibt es bekannte häufige Probleme?
- AFAIK, wenn alle Argumente Konstante Ausdrücke.
- Und was ist, wenn ich Schreibe
POW((unsigned __int64)2, 63)
. Würde das trotzdem als ein konstanter Ausdruck? - Eigentlich ist es komplexer als das, denke ich. Ich denke
constexpr
muss nur ausgewertet werden, wenn sein Ergebnis wird als template-parameter, array gebunden ist, oder andere Integrale Konstante. Zu jeder anderen Zeit ist eine Optimierung. In der Tat, auch wenn Sie angesichts konstanter Ausdruck-Argumente, es könnte erforderlich sein, um die Ausführung zur Laufzeit.constexpr int func(int p) { return !p ? 1 : throw std::exception("HI");}
muss zur Laufzeit ausgewertet, wenn gegeben, eine nicht-null-Eingabe. - Initialisierungen, die Konstante Ausdrücke sind Bestandteil der statischen Initialisierung phase, z.B.
constexpr int a = POW(5, 4);
. Das ist im wesentlichen berechnet werden bei der Kompilierung. Natürlich können Sie aber auch noch verwendenPOW
in anderen Orten. - Es sei denn, das Ergebnis der Funktion ist in der oben genannten Konstanten Ausdrucks "requirerers", dann gibt es einen compile-Zeit-Fehler, da die Ausnahme.
- Ich rannte aus der Kommentar-Raum, aber ja 😀
- Verwandte: stackoverflow.com/questions/14294271/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
constexpr
Funktionen wird werden zur Kompilierzeit ausgewertet, wenn alle seine Argumente Konstante Ausdrücke und das Ergebnis wird in einem Konstanten-Ausdruck als gut. Ein konstanter Ausdruck kann ein literal (wie42
), eine non-type template argument (wieN
imtemplate<class T, size_t N> class array;
), einenum
element-Deklaration (wieBlue
imenum Color { Red, Blue, Green };
, eine weitere variable deklariert constexpr, und so weiter.Sie könnte ausgewertet werden, wenn alle seine Argumente Konstante Ausdrücke und das Ergebnis ist nicht verwendet, in der ein konstanter Ausdruck sein, aber das ist bis zu der Umsetzung.
STATIC_ASSERT_CONSTEXPR( pow(2,3) )
, aber ich bin nicht mit viel Glück...constexpr
Funktionen werden zur Kompilierzeit ausgewertet, wenn alle Argumente Konstante Ausdrücke? Ich glaube, das einzige, was der Standard sagt, ist, dassconstexpr
Funktionen können verwendet werden, in Kontexten, die ausgewertet werden müssen zur compile-Zeit, z.B. template-Argumente. Alles andere ist bis auf den compiler zu entscheiden. Mindestens das ist, was ich habe bislang glaubte.constexpr int f();
und dann deklarieren Sie eine Konstante expressionconstexpr int a = f();
. Ihre Antwort deutet darauf hin, dassa
werden zur Kompilierzeit ausgewertet, weilf
istconstexpr
alle seine Argumente sind auch, und das Ergebnis wird in einerconstexpr
. Aber ich glaube, das ist unbedingt nur wahr, wenna
ist im Kontext erfordert compile-Zeit-Auswertung, z.B. eine template-argument. Auch habe ich gesehen, den link, aber da dieses eine SO beantworten, dazu sind die relevanten Tatsachen, insb. Standard zitiert, soll hier gelegt werden.constexpr
variable ist eine konstanter Ausdruck, die benötigt compile-time-Auswertung. Die standard-Zitate sind nicht-normative Hinweise; die Anforderungen fürconstexpr
Funktionen ausgewertet werden zur compile-Zeit sind implizit alle über den standard, wenn es Gespräche über eine konstanter Ausdruck.a
konnte dann als template-argument oder anderen Kontext benötigt compile-Zeit-Auswertung, die ich glaube implizit erfordert Ihre Auswertung immer getan, zur compile-Zeit. Aber ich sehe Ihren Punkt, Sie sollten Fragen Sie in der ISO-C++ veröffentlichen, um die Aufmerksamkeit von beteiligten bei der Herstellung dieses feature...a
in deinem Beispiel muss ausgewertet werden zur compile-Zeit, und nicht der Hinweis geradezu falsch. Ich bin mir nicht sicher, ob dies tatsächlich gewährleistet der standard an dieser Stelle...constexpr
ist ein konstanter Ausdruck, aber es ist nur sichergestellt, die ausgewertet werden zur compile-Zeit, wenn es als ein konstanter Ausdruck (z.B. als template-argument). Aber was genau bedeutet das?constexpr
Funktion akzeptiert eine Gleitkommazahl (oder in der Tat jede Art, die Sie mögen) und eine ganze Zahl zurückgibt, dann verwenden Sie, dass in einer template non-type-parameter.constexpr size_t check_nonintegral_constexpr(float v) { return sizeof v; } std::array<check_nonintegral_constexpr(pow(2.0, 4))> assertion;
Die Funktion ausgewertet werden zur compile-Zeit, wenn ein konstanter Ausdruck erforderlich ist.
Ist die einfachste Methode, dies zu gewährleisten, ist die Verwendung einer
constexpr
Wert, oderstd::integral_constant
:oder:
oder
oder
std::cout << POW(2, 63) << std::endl
könnte am Ende nicht ausgewertet werden während der compile-Zeit, da cout nicht erforderlich ist, ein konstanter Ausdruck mit dem Wert?constexpr auto
Methode.std::cout << *[](){static constexpr auto expr = POW(1.113, 11); return &expr;}() << std::endl;
static
bedeuten im Grunde "legen Sie es auf die Daten-segment"? Was ist falsch mit einem Zeiger, da kann er nicht verschwinden? @GManNickG Aber die Funktion wird ausgewertet zur compile-Zeit auf jeden Fall, richtig?*[]
. Ich Tat dies, um sicherzustellen, dass die return-Anweisung nicht das Objekt kopieren.#define FORCE_CT_EVAL(func) [](){constexpr auto ___expr = func; return std::move(___expr);}()
operator()
des lambda-Ausdrucks für ein Objekt? Das ist genau das, was ich sehe, mitgdb
. Nicht nur, dassoperator()
vielleicht nicht constexpr selbst und könnten Sie zwingen, run-time-Auswertung.