2015-07-03 16 views
14

C++ Primer (5a edizione) a pagina 240 ha una nota affermando:Non è richiesta una funzione constexpr per restituire un'espressione costante?

"Una funzione constexpr non è tenuto a restituire un'espressione costante".

Una domanda è stata posta al riguardo: can constexpr function return type be a non const?. L'autore di quella domanda ha frainteso la nota.

Ma qual è la corretta comprensione di ciò (le risposte al post citato chiariscono la confusione dell'autore di quel post, ma non rispondono alla mia domanda)?

+4

Grazie Simon per la formattazione della domanda così bene. Ho imparato nuove cose da questo. – AlwaysLearning

+2

Scott Meyers spiega abbastanza bene questo argomento nel suo nuovo libro, Effective Modern C++ – Alejandro

+0

@ Alejandro Quale numero di articolo? – AlwaysLearning

risposta

13

Una funzione (non modello) constexpr deve avere almeno un percorso di esecuzione che restituisca un'espressione costante; formalmente, devono esistere valori di argomento tali che "un'evocazione della funzione [...] potrebbe essere una sottoespressione valutata di un'espressione costante di nucleo" ([dcl.constexpr]/5). Per esempio (ibid.):

constexpr int f(bool b) { return b ? throw 0 : 0; }  // OK 
constexpr int f() { return f(true); }  // ill-formed, no diagnostic required 

Qui int f(bool) è permesso di essere constexpr perché la sua invocazione con valore di argomento false restituisce un'espressione costante.

È possibile avere una funzione constexpr che non può mai restituire un'espressione costante se si tratta di una specializzazione di un modello di funzione che potrebbe avere almeno una specializzazione che restituisce un'espressione costante. Ancora, con quanto sopra:

template<bool B> constexpr int g() { return f(B); } // OK 
constexpr int h() { return g<true>(); } // ill-formed, no diagnostic required 
+0

Qual è l'utilità nel dichiarare 'g ()' come 'constexpr'? Puoi scrivere 'constexpr int a = g ();'? Immagino di no, perché il compilatore non sarà in grado di calcolare il valore di inizializzazione per 'a' in fase di compilazione ... – AlwaysLearning

+0

@ MeirGoldenberg corretto, ma è possibile scrivere 'constexpr int a = g ();', quindi lo standard consente 'g()' di essere 'constexpr'. – ecatmur

+0

Ah, giusto, non verrà compilato se ometto 'constexpr' nella specializzazione! Grazie! – AlwaysLearning

15

A constexpr funzione deve restituire * deve avere un percorso che restituisce un'espressione costante se tutti i parametri sono espressioni costanti. Questo ha davvero senso. Esempio:

constexpr int square(int i){ 
    return i*i; 
} 

std::array<int, square(2)> ia; //works as intended, constant expression 
int i; 
std::cin >> i; 
int j = square(i); //works even though i is not a constant expression 
std::array<int, square(i)> ia; //fails, because square does not (and cannot) 
           //return a constant expression 

* Correzione da chris.

+1

Non sono d'accordo. Finché è possibile che la funzione restituisca un'espressione costante, va bene. È consentito prendere un parametro di espressione costante e restituire un'espressione non costante fintanto che restituisce un'espressione costante un'altra volta (ad es. Http://coliru.stacked-crooked.com/a/a0d9dcadc756749c). Questo argomento è preso dalla domanda a cui l'OP ha collegato. – chris

+1

All'interno della funzione constexpr, i parametri non sono considerati come espressioni costanti. Quindi, anche 'constexpr int foo (int i) {return i; } 'does not * restituisce un'espressione costante *. La formulazione in C++ Primer è un po 'sciocca IMHO. Quello che richiede lo standard è che si deve essere in grado di chiamare una funzione constexpr all'interno di un'espressione costante (esistono argomenti tali che la funzione può essere chiamata all'interno di un'espressione costante). – dyp

Problemi correlati