c++ templates c++11 g++ static-assert

c++ - static_assert falla la compilación aunque la función de plantilla no se llame en ninguna parte



templates c++11 (3)

El estándar dice en [temp.res] / 8

No se emitirá ningún diagnóstico para una definición de plantilla para la cual se pueda generar una especialización válida. Si no se puede generar una especialización válida para una definición de plantilla, y esa plantilla no se crea una instancia, la definición de la plantilla está mal formada, no se requiere diagnóstico. ... [Nota: si se crea una instancia de una plantilla, los errores se diagnosticarán de acuerdo con las otras reglas de este Estándar. Exactamente cuando se diagnostican estos errores es una cuestión de calidad de implementación. - nota final]

No hay ninguna manera posible de crear una instancia de la plantilla de función que se compilará, por lo que la definición de la plantilla está mal formada y, por lo tanto, el compilador puede (aunque no es obligatorio) rechazarla incluso si no se crea una instancia.

Podrías hacer que funcione así:

template<typename T> struct foobar : std::false_type { }; template <typename T> inline T getValue(AnObject&) { static_assert( foobar<T>::value , "this function has to be implemented for desired type"); }

Ahora el compilador no puede rechazar la plantilla de función de forma inmediata, porque hasta que no se instancia, no sabe si habrá una especialización de foobar que tenga value == true . Cuando se crea una instancia, la especialización relevante de foobar<T> creará una instancia y la aserción estática fallará, como se desee.

Yo uso g ++ 4.6.3, (actualmente el paquete predeterminado para ubuntu 12.04) con el indicador c ++ 0x, y me tropiezo con esto:

template <typename T> inline T getValue(AnObject&) { static_assert(false , "this function has to be implemented for desired type"); }

con el error de compilación:

static_assertion failed "this function has to be implemented for the desired type"

a pesar de que todavía no llamo a esta función en ningún lado .

¿Es un error de g ++? ¿No debería instanciarse esta función solo si se llama en algún lugar del código?


Eso es porque la condición no depende de ninguna manera de los parámetros de la plantilla. Por lo tanto, el compilador puede evaluarlo incluso antes de crear una instancia de esa plantilla, y produce el mensaje de error de compilación asociado si la evaluación arroja resultados false .

En otras palabras, esto no es un error. Aunque muchas cosas solo se pueden verificar una vez que se crea una instancia de una plantilla, existen otras verificaciones de validez que un compilador puede realizar incluso antes. Esta es la razón por la que C ++ tiene una búsqueda de nombres de dos fases, por ejemplo. El compilador solo intenta ayudarlo a encontrar errores que son 100% probables de ocurrir.


Esto es realmente un comentario, pero requiere un ejemplo de código.

La redacción del estándar sagrado para static_assert no limita su efecto al código instanciado.

Sin embargo, el código

template <typename T> inline T getValue(int&) { typedef char blah[-1]; // Common C++03 static assert, no special semantics. } int main() {}

tampoco se puede compilar con MinGW g ++ 4.7.2, lo que acentúa la pregunta.

Creo que la respuesta es que g ++ es correcto, y que Visual C ++ 11.0, que no produce un error de compilación para esto, está equivocado, pero me resultaría difícil proporcionar el análisis relevante en términos de los versos del patrón sagrado.

Una consecuencia práctica de la diferencia del compilador es que actualmente no puede confiar en el comportamiento.