Wo in C ++ 14 Standard heißt es, dass eine non-consxpr-Funktion nicht in einer constexpr-Funktion verwendet werden kann?

7

Zum Beispiel wird der folgende Code nicht kompiliert, es sei denn incr() wird als constexpr deklariert:

%Vor%

Betrachtet man §7.1.5 / 3 in C ++ 14, haben wir:

  

Die Definition einer consExpr-Funktion muss Folgendes erfüllen   Einschränkungen:
  (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

nicht enthält      

(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.

    
Ayrosa 14.12.2015, 17:17
quelle

3 Antworten

10

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).

    
Barry 14.12.2015, 17:20
quelle
8

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%     
bames53 14.12.2015 17:46
quelle
4

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.

    
Ben Voigt 14.12.2015 17:20
quelle