2015-01-02 9 views
35

gcc compila il seguente codice senza preavviso:È un'estensione del compilatore conforme per il trattamento delle funzioni di libreria standard di constexpr come constexpr?

#include <cmath> 

struct foo { 
    static constexpr double a = std::cos(3.); 
    static constexpr double c = std::exp(3.); 
    static constexpr double d = std::log(3.); 
    static constexpr double e1 = std::asin(1.); 
    static constexpr double h = std::sqrt(.1); 
    static constexpr double p = std::pow(1.3,-0.75); 
}; 

int main() 
{ 
} 

Nessuna delle funzioni di libreria standard utilizzati in precedenza sono funzioni constexpr, si è permesso di usarli in cui una costante espressione è richiesto sia da the draft C++11 standard e draft C++14 standard sezione 7.1.5[dcl.constexpr]:

[...] Se viene inizializzato da una chiamata del costruttore, quella chiamata deve essere un'espressione costante (5.19). In caso contrario, o se un identificatore constexpr è utilizzato in una dichiarazione di riferimento, ogni espressione piena che appare nel sua inizializzazione deve essere un'espressione costante. [...]

anche quando si usano -std=c++14 -pedantic o -std=c++11 -pedantic nessun avviso sono generato (see it live). Utilizzando -fno-builtin produce errori (see it live), che indica che sono stati trattati la versione builtin di queste funzioni di libreria standard, come se fossero in cui constexpr

Mentre clang non consente il codice con qualsiasi combinazione di bandiere che ho provato.

Quindi questo è un estensione gcc per il trattamento di funzioni almeno alcuni builtin come se fossero funzioni constexpr anche se la norma non richiede esplicitamente loro di essere. Mi sarei aspettato di ricevere almeno un avvertimento in modalità di conformità rigorosa, è un'estensione conforme?

risposta

35

TL; DR

In C++ 14 questo non è esplicitamente consentito, anche se in 2011 è apparso come questo caso sarebbe stato esplicitamente consentito. Non è chiaro se per C++ 11 questo sia sceso sotto lo as-if rule, non credo che lo faccia poiché altera il comportamento osservabile, ma quel punto non è stato chiarito nel problema di cui faccio riferimento in seguito.

dettagli

La risposta a questa domanda si è spostata con lo status evoluzione di LWG issue 2013 che si apre con:

Supponiamo che una particolare funzione non è etichettato come constexpr nello standard , ma che, in alcune particolari implementazioni, è possibile scrivere all'interno dei vincoli di constexpr. Se un implementatore etichetta una funzione come constexpr, è una violazione dello standard o è un'estensione conforme?

In C++ 11 Non è chiaro se il come-se regola permesso questo, ma la proposta orignal avrebbe esplicitamente consentito una volta che è stata accettata e possiamo vedere di seguito nella segnalazione gcc I di riferimento, questa era l'ipotesi fatta dal team di gcc.

Il consenso per consentire questo spostamento nel 2012 e la proposta modificata e in C++ 14 questa è un'estensione non conforme. Ciò si riflette nel progetto di 14 sezione standard C++ 17.6.5.6[constexpr.functions] che dice:

[...] L'attuazione non deve dichiarare qualsiasi funzione di libreria firma standard come constexpr ad eccezione di quelli dove è esplicitamente necessaria. [..]

e anche se un rigoroso lettura di questo sembra lasciare qualche scappatoia per il trattamento di un builtin implicitamente, come se si trattasse di un constexpr possiamo vedere dalla seguente citazione nella emettere che l'intenzione era quella di prevenire divergenze nelle implementazioni da quando id Codice entical potrebbe produrre un comportamento diverso quando si utilizza SFINAE (sottolineatura mia):

Qualche preoccupazione espressa quando ha presentato a pieno commissione al momento della votazione allo stato di WP che la questione era stata risolta senza una sufficiente pensiero di le conseguenze per le implementazioni di librerie divergenti , in quanto gli utenti di possono utilizzare SFINAE per osservare un comportamento diverso dal codice identico .

Possiamo vedere dalla segnalazione di bug gcc [C++0x] sinh vs asinh vs constexpr che la squadra invocato la risoluzione proposta precedente di LWG 2013 che dice:

[...] Inoltre, un'implementazione può dichiarare qualsiasi funzione di essere constexpr se la definizione di quella funzione soddisfa le necessarie vincoli [...]

al momento di decidere se questo cambiamento per le funzioni matematiche è stato permesso in stretta c modalità di funzionamento.

Per quanto posso dire questo sarebbe conforme se questo abbiamo ricevuto un avviso in modalità di conformità stretta cioè utilizzando -std=c++11 -pedantic o se è stato disabilitato in questa modalità.

Nota, ho aggiunto un commento alla segnalazione di bug che spiega che la risoluzione è cambiata da quando questo problema era stato originariamente risolto.

Jonathan Wakely pointed out in un'altra domanda uno più recente discussion e sembra probabile che il rapporto bug di gcc verrà riaperto per risolvere questo problema di conformità.

Che dire intrinseche

Compiler intrinsics non sono coperti dalla norma e quindi, per quanto posso dire che dovrebbero essere esenti da questa regola, in modo da utilizzare:

static constexpr double a = __builtin_cos(3.); 

dovrebbe essere consentito. Questa domanda è venuto su nel bug report e l'opinione di Daniel Krugler era:

[...] Le funzioni di libreria e gli altri intrinseche possono probabilmente essere considerate come eccezioni, perché non sono tenuti ad essere "spiegabile" di regole di linguaggio normali.

+0

@Walter Ho aggiunto una sezione 'LT; DR'. Fammi sapere se ci sono altri punti che posso chiarire. –

+0

E gli intrinsechi? – Columbo

+0

Non penso sia utile parlare di intrinseche del compilatore. Tutti i nomi che iniziano con '__' sono riservati per l'implementazione e l'implementazione definisce la loro semantica. È del tutto ragionevole che la semantica delle funzioni specifiche dell'implementazione, siano esse intrinseche o meno, sia definita come "constexpr", a discrezione del realizzatore. –

Problemi correlati