Quello che stai cercando è § 5.19:
A condizionale espressionee è un nucleo costante espressione a meno che la valutazione del e, seguendo le regole della macchina astratta (1.9), valuterà una delle seguenti espressioni:
Questo si applica alla valutazione di un'espressione che è una chiamata di funzione constexpr
. Cioè, chiamare una funzione constexpr
sarà una 'espressione costante di nucleo' se la valutazione della funzione, cioè l'esecuzione del corpo della funzione secondo le regole della macchina astratta C++, non fa nessuna delle cose proibite nell'elenco dato in § 5.19.
Uno degli elementi della lista è:
- un'invocazione di una funzione diversa da [...] una funzione constexpr
Quindi, per applicare questo al tuo esempio : la valutazione dell'espressione foo()
valuta una chiamata a una funzione incr()
che non è una funzione di constexpr, il che significa che l'espressione foo()
non è un'espressione di costante di nucleo.
Inoltre, dal momento che quanto sopra è vero per tutte le possibili invocazioni della vostra funzione foo
, la regola al § 7.1.5/5 calci e significa che il programma esempio è mal formato, senza diagnostica richiesta, anche se non si in realtà chiamare foo()
.
Come Ben Voigt indica una funzione constexpr può contenere chiamate a funzioni non consexpr, purché la valutazione particolare della funzione realtà non valutare tale chiamata di funzione (o appare in un contesto che fa non richiede un'espressione costante).
Le restrizioni in 5.19 riguardano solo le espressioni che vengono effettivamente valutate come parte della valutazione di un'espressione.
Ad esempio:
#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';
}
Probabilmente la pena notare [domanda precedente] (http://stackoverflow.com/q/34211688/1708801) che copre molto stesso terreno, anche se da una prospettiva differente . –
@ShafikYaghmour Mi piacerebbe davvero avere i vostri commenti su questa nuova domanda. – Ayrosa
nota che le cose che hai citato sono * necessarie * ma non * sufficienti * condizioni, cioè se tali condizioni sono violate, allora il codice è mal formato, tuttavia se non vengono violate allora il codice può essere o non essere corretto e noi devono guardare ad altre parti della specifica. –