static_assert depende del parámetro de plantilla sin tipo (comportamiento diferente en gcc y clang)

template  struct Hitchhiker { static_assert(sizeof(answer) != sizeof(answer), "Invalid answer"); }; template  struct Hitchhiker {}; 

Al intentar deshabilitar la instanciación de plantilla general con static_assert , descubrí que el código anterior en clang genera el error de static_assert incluso cuando la plantilla no está instanciada, mientras que gcc genera el error de afirmación solo al crear Hitchhiker con un parámetro que no sea 42 .

Mientras jugueteaba, encontré que esto afirmaba:

 template  struct Hitchhiker { static_assert(sizeof(int[answer]) != sizeof(int[answer]), "Invalid answer"); }; template  struct Hitchhiker {}; 

se comporta de la misma manera en ambos comstackdores: la afirmación se activa solo cuando se crea una instancia de la plantilla general.

¿Qué dice el estándar, qué comstackdor tiene razón?

 g++ 4.9.2 clang++ 3.50 

Cotizaciones encontradas por @TartainLlama

Si una instanciación hipotética de una plantilla inmediatamente posterior a su definición estaría mal formada debido a una construcción que no depende de un parámetro de plantilla, el progtwig está mal formado; no se requiere diagnóstico.

N4296 [temp.res] / 8

Esto se aplica inmediatamente después de que se define la plantilla primaria (la que tiene static_assert en ella). Entonces, la especialización posterior (para 42 ) no se puede considerar, ya que aún no existe.

La siguiente pregunta es si static_assert( sizeof(answer) != sizeof(answer), depende de la answer . Semánticamente no lo hace, sintácticamente, y de manera estándar:

Dentro de una plantilla, algunos constructos tienen semántica que puede diferir de una instanciación a otra. Tal construcción depende de los parámetros de la plantilla.

N4296 [temp.dep] / 1

El sizeof(answer) != sizeof(answer) construcción de sizeof(answer) != sizeof(answer) no difiere de una instanciación a otra. Entonces tal construcción no depende de los parámetros de la plantilla. Lo que significa que el static_assert completo no depende del parámetro de la plantilla.

Por lo tanto, su progtwig está mal formado, no se requiere diagnóstico. La emisión de un diagnóstico arbitrario (como la falla static_assert ) es un comportamiento válido del comstackdor. Perder el problema es un comportamiento válido del comstackdor. El comportamiento de un progtwig comstackdo a partir de un progtwig mal formado, sin necesidad de diagnóstico no está definido por el estándar: es un comportamiento indefinido. Los demonios nasales están permitidos.

Los bashs de lujo (como sizeof(int[answer])!=sizeof(int[answer]) pueden complacer al comstackdor de dios actual, pero no hacen que tu progtwig esté mejor formado.

Podría hacer un caso en el que es poco probable que el comstackdor pueda atraparlo, pero el mal formado permanece independientemente de la capacidad del comstackdor para atraparlo con él. Como regla general, C ++ quiere dejar a sí mismo (y a sus comstackdores) libertad para encontrar el código de plantilla no válido “antes que la instanciación”; esto significa que el código de plantilla debe producir código posiblemente legal.

Es posible que desee algo como =delete con un mensaje adjunto.

Ambos comstackdores son correctos. Desde [temp.res] / 8:

Si no se puede generar una especialización válida para una plantilla, y esa plantilla no se crea una instancia, la plantilla está mal formada, no se requiere diagnóstico.

No existe una especialización válida que se pueda generar a partir de la plantilla principal Hitchhiker , por lo que está mal formada, no se requiere diagnóstico. clang elige emitir un diagnóstico de todos modos.

Si solo quiere permitir 42 , simplemente no defina la plantilla general:

 template  struct Hitchhiker; template <> struct Hitchhiker<42> {};