2016-06-02 28 views
15

GCC v6.1 (il risultato è lo stesso con v5.1) compilato correttamente il codice qui sotto con bandiere -std=c++11 -Wall -Wextra -Wpedantic, ma produce questo avvertimento:Perché la compilazione con C++ 11 ha successo nonostante si usi la funzionalità C++ 14?

variable templates only available with -std=c++14 or -std=gnu++14 

Il codice:

#include <iostream> 

template <typename T> 
struct ParamMetadata { 
     T min; 
     T max; 
}; 

template <class T1, class T2> 
class FooMap {}; 

template <typename T> 
// WARNING PRODUCED ON THIS LINE 
extern FooMap<int, ParamMetadata<T> > metadataHashmap; 

int main() { 
     return 0; 
} 

Clang v3 0,8 produce un avviso simile:

variable templates are a C++14 extension [-Wc++14-extensions] 

Se questa è una caratteristica disponibile solo in C++ 14, perché lo fa compilato con C++ 11 bandiera proprio bene e I C eseguire l'eseguibile? Non dovrebbe essere un errore fatale?

+3

Utilizzare '-pedantic-errors' per un errore –

+0

@PiotrSkotnicki Sure, ma come può il programma essere compilato ed eseguito senza la funzionalità richiesta? – DBedrenko

+1

Perché pensi che funzioni senza la funzione richiesta? –

risposta

12

Lo standard C++ non ha il concetto di "errore fatale del compilatore". I programmi sono mal formati con una diagnostica richiesta o mal formati senza necessità di diagnostica o ben formati.

In C++, l'unico requisito che lo standard inserisce in una diagnostica del programma non formattata consiste nel visualizzare una diagnostica . I contenuti di quella diagnostica non sono definiti. Che altro succede oltre a quella diagnostica non è definita.

Molti compilatori implementano estensioni allo standard C++ che viene loro richiesto di compilare in base a tali programmi altrimenti mal formati e produrre un eseguibile eseguibile. Se sono conformi a uno standard, l'unica cosa che devono fare è stampare un messaggio di avviso (che soddisfi i requisiti diagnostici dello/degli standard C++).

In questo caso, viene stampato un messaggio di avviso che è stata utilizzata una funzione C++ 14. Ora ha fatto con successo quello che lo standard C++ 11 richiede con il tuo programma mal formato. Produce anche un eseguibile che fa ciò che il tuo programma farebbe se fosse usata quella caratteristica dello standard C++ 14: è libera di farlo, poiché lo standard a questo punto non pone restrizioni su ciò che fa il programma una volta che è un programma malformato in C++ 11.

Se non si desidera questa opzione, i compilatori hanno spesso un flag warnings-as-errors e vari flag strict e pedantic che bloccano le estensioni allo standard che utilizzano. Quindi l'errore sopprimerà la generazione dell'eseguibile e non sarai più confuso.

gcc per impostazione predefinita si presuppone che si desideri compilare il codice fornito in qualcosa anziché agire come uno standardforcer e genera solo errori quando non ha un modo ragionevole di interpretare il codice come un programma che probabilmente corrisponde alle proprie intenzioni . Fornisce flag per passare a una modalità rigorosa e pedante.


In modo divertente, la stampa di un singolo carattere di spazio soddisfa il requisito per visualizzare una diagnosi.Lo standard C++ può essere letto in modo patologico al fine di generare una scarsa qualità di implementazione nel compilatore: generare uno standard ostile al compilatore non vale la pena.

+0

Grazie mille e tutti coloro che hanno risposto alla mia domanda. Che risposta eccellente! Oggi ho imparato molto sui compilatori. Una buona cosa da aggiungere (che è la soluzione pratica alla mia domanda) è usare flag '-pendatic-errors' (in combinazione con' -std = C++ 11 -pedantic'), che farà sì che il compilatore lanci un errore quando viene utilizzata una funzionalità di C++ 14. – DBedrenko

+2

"Produce anche un eseguibile che esegue ciò che il programma farebbe se fosse compilato secondo lo standard C++ 14" - solo rispetto a questa particolare caratteristica: potrebbero esserci altre parti del programma che sono ancora compilate con successo con C++ 11 regole che sarebbero state diverse in C++ 14. –

2

Niente "dovrebbe essere un errore fatale". Se il compilatore scrive un messaggio che ti dice che cosa è successo ha adempiuto ai suoi obblighi.

Ora sei libero di prendere una decisione informata sull'opportunità di considerare il codice come un errore fatale e modificare il codice; o trattarlo come se fosse C++ 14 e seguirlo.

È possibile utilizzare l'interruttore -Werror (cambia la parola "avviso" su "errore" nel messaggio) se si ritiene che sarebbe di aiuto.

+0

Grazie per la risposta. Se il programma è in grado di funzionare senza questa funzione, allora l'implicazione della mia domanda è qual è invece il comportamento di 'FooMap' quando compilato con C++ 11? La parte "filly informed" nella tua risposta è quella che sarebbe una risposta molto utile. – DBedrenko

+1

@SpaghettiCat Non è "eseguito senza questa funzione". La funzione è completamente compilata come se si stesse usando '-std = C++ 14'. L'unica differenza è che ricevi un avvertimento. – HolyBlackCat

+0

@HolyBlackCat Oh giusto .... quindi il compilatore impone l'uso di '-std = C++ 14' quando vede il codice che è solo C++ 14? Non ero a conoscenza di questo comportamento ... – DBedrenko