Quotes found by @TartainLlama
If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required.
N4296 [temp.res]/8
This applies immediately after the primary template is defined (the one with the static_assert
in it). So the later specialization (for 42
) cannot be considered, as it does not exist yet.
The next question is if static_assert( sizeof(answer) != sizeof(answer),
depends on answer
. Semantically it does not, syntactically it does, and standard-wise:
Inside a template, some constructs have semantics which may differ from one instantiation to another. Such a construct depends on the template parameters.
N4296 [temp.dep]/1
The construct sizeof(answer) != sizeof(answer)
does not differ from one instantiation to another. So such a construct does not depend on the template parameters. Which means the entire static_assert
does not depend on the template parameter.
Thus your program is ill formed, no diagnostic required. Issuing an arbitrary diagnostic (such as the static_assert
failing) is valid compiler behavior. Missing the problem is valid compiler behavior. The behavior of a program compiled from an ill formed, no diagnostic required program is not defined by the standard: it is undefined behavior. Nasal demons are permitted.
Fancy attempts (like sizeof(int[answer])!=sizeof(int[answer])
may please the current god compiler, but does not make your program more well formed.
You could make a case where the compiler is unlikely to be able to catch you at it, but the ill-formed-ness remains regardless of the ability for the compiler to catch you with it. As a general rule, C++ wants to leave itself (and its compilers) freedom to find invalid template code "earlier than instantiation"; this means that template code must produce possibly legal code.
It is possible you want something like =delete
with a message attached.
static_assert
declaration is considered a class member, and should come into being only when the class is instantiated. By the way, you could just leave the primary template a declaration without a definition. – Haunchshould come into being only when the class is instantiated
I don't think that it is true: E.g.static_assert(sizeof(int) != sizeof(int), "some error");
will generate error when member of a template, even if the template is never instantiated. – Swirlstatic_assert
is dependent on a template parameter – SwirlHitchhiker
not to be instantiated with random parameters, you can just declare the template astemplate <int> struct Hitchhiker;
. The diagnosis is not customisable, then, but it would work identically on both Clang and gcc. – Joachim