Domanda

Come probabilmente sapete, C ++ 11 introduce la parola constexpr.

C ++ 11 ha introdotto la parola chiave constexpr, che permette all'utente di garanzia che un costruttore funzione o un oggetto è una fase di compilazione costante. [...] Questo consente al compilatore di comprendere e verificare che [nome della funzione] è un compile-time costante.

La mia domanda è perché ci sono tali restrizioni severe in forma delle funzioni che possono essere dichiarati. Capisco volontà di garantire che la funzione è pura, ma considerare questo:

L'uso di constexpr su una funzione impone alcune limitazioni su quello tale funzione può fare. In primo luogo, la funzione deve avere un ritorno non-vuoto genere. In secondo luogo, il corpo della funzione non può dichiarare variabili o definire nuovi tipi. In terzo luogo, il corpo può contenere solo dichiarazioni, dichiarazioni nulli e una singola istruzione di ritorno. Deve esistere valori degli argomenti tali che, dopo la sostituzione argomento, l'espressione nel ritorno dichiarazione produce un'espressione costante.

Ciò significa che questa funzione pura è illegale:

constexpr int maybeInCppC1Y(int a, int b)
{
    if (a>0)
        return a+b;
    else
        return a-b;
  //can be written as   return  (a>0) ? (a+b):(a-b); but that isnt the point
}

Inoltre non puoi definire variabili locali ... :( Quindi mi chiedo è questa una decisione di progettazione, o non compilatori succhiare quando si tratta di dimostrare la funzione a è puro?

È stato utile?

Soluzione

Il motivo avresti bisogno di scrivere istruzioni invece di espressioni è che si vuole sfruttare le funzionalità aggiuntive di dichiarazioni, in particolare la capacità di loop. Ma per essere utile, che richiederebbe la capacità di dichiarare le variabili (anche vietato).

Se si combina un impianto per looping, con le variabili mutevoli, con ramificazione logica (come nelle dichiarazioni if) allora si ha la possibilità di creare un loop infinito. Non è possibile determinare se un tale loop mai terminate ( il problema della terminazione ). Così alcune fonti potrebbe causare il compilatore per appendere.

Utilizzando funzioni pure ricorsive è possibile causare ricorsione infinita, che può essere dimostrato di essere equivalentemente potente per le capacità loop sopra descritti. Tuttavia, C ++ ha già quel problema al momento della compilazione - che si verifica con l'espansione del modello -. E così i compilatori hanno già avere un interruttore per "profondità template stack" in modo da sapere quando a rinunciare

Quindi, le restrizioni sembrano progettati per garantire che questo problema (di determinare se un C ++ compilation potrà mai finire) non c'è niente di più spinoso di quanto non lo sia già.

Altri suggerimenti

Le regole per funzioni constexpr sono progettati in modo tale che si tratta di impossibile di scrivere una funzione constexpr che ha effetti collaterali.

Per richiedere constexpr non avere effetti collaterali diventa impossibile per un utente per determinare dove / quando in realtà è stato valutato. Ciò è importante poiché le funzioni constexpr possono accadere sia a tempo di compilazione e corrono momento a discrezione del compilatore.

Se gli effetti collaterali sono stati autorizzati allora non ci sarebbe bisogno di essere alcune regole circa l'ordine in cui sarebbero stati osservati. Questo sarebbe incredibilmente difficile da definire -. Ancora più difficile di quanto il problema static ordine di inizializzazione

Un relativamente semplice insieme di regole per garantire queste funzioni ad essere effetto collaterale è libero di richiedere che siano solo una singola espressione (con alcune restrizioni in più in cima a quello). Questo suoni che limitano inizialmente e esclude l'istruzione if come avrete notato. Mentre quel caso avrebbe avuto effetti collaterali che avrebbe introdotto la complessità in più nelle regole e dato che è possibile scrivere le stesse cose utilizzando l'operatore ternario o in modo ricorsivo non è davvero un affare enorme.

n2235 è la carta che propone l'aggiunta constexpr in C ++. Si discute il razionale per la progettazione - la citazione in questione sembra essere questo uno da una discussione sui distruttori, ma rilevanti in generale:

La ragione è che una costante espressione deve essere valutata dal compilatore al momento traduzione come qualsiasi altro letterale di tipo ad incasso; in particolare, non è consentito osservabile effetto collaterale.

È interessante notare che il documento menziona anche che una proposta precedente ha suggerito il compilatore capito automaticamente quali funzioni erano constexpr senza la nuova parola chiave, ma questo è risultato essere unworkably complessa, che sembra sostenere la mia idea che le regole sono state progettate per essere semplice.

(ho il sospetto che ci saranno altre citazioni nei riferimenti citati nella carta, ma questo copre il punto chiave della mia argomentazione sui effetti collaterali)

In realtà il comitato di standardizzazione C ++ sta pensando di rimozione di alcuni di questi vincoli per C ++ 14. Consultare il seguente documento di lavoro http://www.open-std.org /JTC1/SC22/WG21/docs/papers/2013/n3597.html

Le restrizioni potrebbero certamente essere sollevato un bel po 'senza abilitare codice che non può essere eseguita durante la fase di compilazione, o che non può essere dimostrato di sempre battuta d'arresto. Tuttavia Credo che non è stato fatto perché

  • che complicherebbe il compilatore per il guadagno minimo. Compilatori C ++ sono abbastanza complesse come è

  • specificando esattamente quanto è consentita senza violare le restrizioni di cui sopra sarebbe stato in termini di tempo, e dato che le caratteristiche desiderate sono state rinviate al fine di ottenere il fuori standard della porta, probabilmente era scarso incentivo per aggiungere più lavoro (e un ulteriore ritardo dello standard) per il poco guadagno

  • alcune delle restrizioni sarebbe stato sia piuttosto arbitraria o piuttosto complicata (soprattutto sui cicli, dato che C ++ non ha il concetto di incrementazione nativo per ciclo, ma sia la condizione di fine e il codice di incremento avere essere esplicitamente specificato nel for, rendendo possibile l'utilizzo di espressioni arbitrarie per loro)

Naturalmente, solo un membro del comitato standard potrebbe dare una risposta autorevole se le mie supposizioni sono corrette.

Credo constexpr è solo per gli oggetti const. Intendo; ora è possibile avere gli oggetti const statici, come costrutti String::empty_string statico (senza l'hacking!). Questo può ridurre il tempo prima di 'main' chiamato. E gli oggetti const statici possono avere funzioni come .length(), operator==,... quindi questo è il motivo per cui è necessario un 'expr'. In 'C' è possibile creare le strutture costanti statiche come di seguito:

static const Foos foo = { .a = 1, .b = 2, };

Linux kernel ha tonnellate di questo tipo classi. In C ++ si potrebbe fare questo ora con constexpr.

Nota: Non lo so, ma il codice qui sotto non devono essere accettati così come se la versione:

constexpr int maybeInCppC1Y(int a, int b) { return (a > 0) ? (a + b) : (a - b); }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top