Question:
#include <type_traits>
template<typename T>
struct A {
static_assert(!std::is_same_v<int, T>);
};
template<typename T>
struct B {
void foo() {
A<int>{};
}
};
int main() {
}
Why does this program compile with gcc and msvc ( 1 and 2 ) but not with clang ( 3 )? Should it compile according to the standard?
Answer:
Formally – Clang is wrong, the code should compile. Since foo
is not used anywhere, it should not be instantiated.
Therefore, A<int>
must not be instantiated either, and static_assert
must not fire.
But in general, in the spirit of the standard, the code should be ill-formed, no diagnostic required (which would mean that the code is invalid, and that all three compilers comply with the standard) because of this section:
[temp.res]/8.1
8 The validity of a template may be checked prior to any instantiation. [ Note: Knowing which names are type names allows the syntax of every template to be checked in this way. – end note ] The program is ill-formed, no diagnostic required, if:
(8.1) – no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or
…
(emphasis mine)
That is, if the code in the template is incorrect for absolutely all possible sets of template arguments, then the program is invalid (but an error message is not guaranteed).
foo
is not valid for all T
, but since foo()
itself is not a template, this section does not apply to it.
Why do I say "in the spirit of the standard"?
Exists:
CWG issue 1253 : Generic non-template members
Section : 17.8 [temp.spec] Status : drafting Submitter : Nikolay Ivchenkov Date : 2011-03-06
Many statements in the Standard apply only to templates, for example, 17.7 [temp.res] paragraph 8:
If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required.
This clearly should apply to non-template member functions of class templates, not just to templates per se. Terminology should be established to refer to these generic entities that are not actually templates.
(Thanks to @StoryTeller .)
Which just states that sections like [temp.res]/8.1
should apply not only to templates, but also to non-template members of template classes, etc.
Judging by
Status : drafting
The committee agrees that this needs to be corrected, but they have not yet decided on specific changes to the text of the standard on this topic.