GCC (8.3, 9.1), Clang (7, 8) and MSVC (19.20) differ is their ability to compile this code:
struct C;
template<typename T> struct S {
void foo() {
// C2 c;
C c;
}
};
class C {};
int main() {
S<int> s;
s.foo();
return 0;
}
GCC and MSVC accept it, whereas Clang rejects it. Clang rejects it even if I make foo
itself a template and/or do not call it at all.
My understanding is that foo
is not instantiated unless it is called, and it is instantiated at the point where it is called. At that point C
is complete, and the code should compile. Is this a reasoning of GCC?
As a side note, if foo
is not called, MSVC accepts the code even if I replace C
with an undeclared C2
inside foo
- in this case it seems to just check the function body to be syntactically correct.
Which behaviour is correct according to the Standard? If it is Clang's, why does the Standard forbids the flexibility that GCC gives?
This is ill-formed, no diagnostic required, due to [temp.res]/8:
The program is ill-formed, no diagnostic required, 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, or [...]
- [...]
So the whole program is bad, but implementations aren't required to diagnose it. Clang does, which is good for clang, gcc and MSVC don't, which isn't wrong.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With