Zum Beispiel wird der folgende Code nicht kompiliert, es sei denn incr()
wird als constexpr
deklariert:
Betrachtet man §7.1.5 / 3 in C ++ 14, haben wir:
Die Definition einer consExpr-Funktion muss Folgendes erfüllen Einschränkungen:
nicht enthält
(3.1) - es soll nicht virtuell sein (10.3); (3.2) - sein Rückgabetyp muss ein Literaltyp sein; (3.3) - jeder seiner Parametertypen muss ein Literaltyp sein; (3.4) - sein Funktionskörper soll = delete, = default oder eine zusammengesetzte Anweisung sein, die(3.4.1) - eine asm-Definition,
(3.4.2) - eine goto Aussage,
(3.4.3) - ein Try-Block oder ein
(3.4.4) - eine Definition einer Variablen von nicht literaler Typ oder von statischer oder Thread-Speicherdauer oder für welche Es wird keine Initialisierung durchgeführt.
Zwei Absätze später, in [dcl.constexpr] / 5:
Für eine nicht vordefinierte, nicht vordefinierte
constexpr
-Funktion oder eine Nicht-Vorlage, nicht voreingestellt, nicht erben conexpr-Konstruktor, wenn keine Argumentwerte existieren, so dass ein Aufruf der Funktion oder des Konstruktors erfolgt könnte ein ausgewerteter Unterausdruck eines Kernkonstantenausdrucks (5.20) oder für einen Konstruktor eine Konstante sein Initialisierer für irgendein Objekt (3.6.2), das Programm ist schlecht gebildet; keine Diagnose erforderlich.
Es gibt kein Argument, so dass foo()
aufgrund von incr()
ein zentraler Konstantenausdruck sein könnte, daher ist das Programm schlecht formatiert (NDR).
Was Sie suchen, ist § 5.19:
Ein Bedingungsausdruck e ist ein Kernkonstantenausdruck, es sei denn die Auswertung von e folgt den Regeln der abstrakten Maschine (1.9) , würde einen der folgenden Ausdrücke auswerten:
Dies gilt für die Auswertung eines Ausdrucks, der ein constexpr
Funktionsaufruf ist. Das heißt, das Aufrufen einer constexpr
-Funktion ist ein "Kernkonstantenausdruck", wenn das Auswerten der Funktion, dh das Ausführen des Rumpfs der Funktion gemäß den Regeln der abstrakten C ++ - Maschine, keine der in der Liste in § 5.19.
Einer der Punkte in der Liste ist:
- Aufruf einer anderen Funktion als [...] einer constexpr-Funktion
Um dies auf Ihr Beispiel anzuwenden: Wenn Sie den Ausdruck foo()
auswerten, wird ein Aufruf an eine Funktion incr()
ausgewertet, die keine conexpr-Funktion ist, was bedeutet, dass der Ausdruck foo()
kein Kernkonstantenausdruck ist.
Da das obige auch 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 fehlerhaft ist, keine Diagnose erforderlich ist, selbst wenn Sie es sind Rufen Sie niemals foo()
auf.
Wie Ben Voigt darauf hinweist, kann eine consExpr-Funktion Aufrufe an Nicht-Consexpr-Funktionen enthalten, solange die jeweilige Auswertung der Funktion keinen solchen Funktionsaufruf tatsächlich auswertet (oder in einem Kontext erscheint, der keine Konstante benötigt) Ausdruck).
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:
%Vor%Tut es nicht.
Folgendes ist erlaubt, obwohl es genau das tut, was Sie vermuten, ist verboten:
%Vor% Der Code in Ihrer Frage wird von der Regel, die Barry in seiner Antwort zitiert, nicht zugelassen. Aber in meiner Variation gibt es eine Reihe von Parametern (insbesondere false
), mit denen der Aufruf von foo
zu einem konstanten Ausdruck für die Kompilierung führt.
Beachten Sie, dass eine Diagnose nicht erforderlich ist - ein kompilierender Compiler könnte auch Ihre Version kompilieren.
Tags und Links c++ language-lawyer c++14 constexpr