¿Por qué compilar con C++ 11 es exitoso a pesar de usar la característica C++ 14?
c++11 gcc (2)
GCC v6.1 (el resultado es el mismo con v5.1) compila con éxito el código siguiente con las banderas -std=c++11 -Wall -Wextra -Wpedantic
, pero produce esta advertencia:
variable templates only available with -std=c++14 or -std=gnu++14
El código:
#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.8 produce una advertencia similar:
variable templates are a C++14 extension [-Wc++14-extensions]
Si esta es una característica solo disponible en C ++ 14, ¿por qué se compila con el indicador de C ++ 11 bien y puedo ejecutar el ejecutable? ¿No debería ser un error fatal?
El estándar C ++ no tiene el concepto de "error de compilación fatal". Los programas están mal formados con un diagnóstico requerido, o mal formados sin un diagnóstico requerido, o bien formados.
En C ++, el único requisito que el estándar coloca en un diagnóstico de programa mal formado es mostrar un diagnóstico 1 . Los contenidos de ese diagnóstico no están definidos. Lo que más sucede además de ese diagnóstico no está definido.
Muchos compiladores implementan extensiones al estándar de C ++ que se les dice que compilen para que tomen programas mal formados y produzcan un ejecutable ejecutable. Si cumplen con un estándar, lo único que deben hacer es imprimir un mensaje de advertencia (que cumpla con los requisitos de diagnóstico de los estándares de C ++).
En este caso, está imprimiendo un mensaje de advertencia de que usó una función de C ++ 14. Ahora ha hecho con éxito lo que requiere el estándar C ++ 11 con su programa mal formado. También produce un archivo ejecutable que hace lo que haría su programa si se utilizara esa característica del estándar C ++ 14: es libre de hacerlo, ya que el estándar en este punto no impone restricciones a lo que hace el programa una vez que es un Programa C ++ 11 mal formado.
Si no desea esta opción, los compiladores suelen tener un indicador de warnings-as-errors
y varios indicadores strict
y pedantic
que bloquean las extensiones al estándar que utilizan. Luego, el error suprimirá la generación del ejecutable y ya no estarás confundido.
gcc de forma predeterminada asume que realmente desea compilar el código provisto en algo, en lugar de actuar como un ejecutor de normas, y solo genera errores cuando no tiene una manera razonable de interpretar su código como un programa que probablemente coincida con sus intenciones. Proporciona banderas para cambiarlo a un modo estricto y pedante.
1 Sorprendentemente, la impresión de un único carácter de espacio satisface el requisito de mostrar un diagnóstico. El estándar de C ++ se puede leer de forma patológica para generar una calidad de implementación deficiente en su compilador: no vale la pena generar un estándar hostil a prueba de compiladores.
Nada "debería ser un error fatal". Si el compilador escribe un mensaje diciéndole lo que sucedió, cumplió con sus obligaciones.
Ahora tiene la libertad de tomar una decisión totalmente informada sobre si tratar el código como si tuviera un error fatal y cambiarlo; o tratarlo como si fuera C ++ 14 e ir con él.
Puede usar el interruptor -Werror
(cambia la palabra "advertencia" a "error" en el mensaje) si cree que sería útil.