Given the following example code
struct S;
template<typename>
class C
{
public:
void f(bool b)
{
if (b)
g();
}
void g()
{
S{};
}
};
int main()
{
C<int>{}.f(false);
}
GCC correctly reports the following:
example.cpp: In instantiation of 'void C< <template-parameter-1-1> >::g() [with <template-parameter-1-1> = int]':
10 : required from 'void C< <template-parameter-1-1> >::f(bool) [with <template-parameter-1-1> = int]'
21 : required from here
15 : error: invalid use of incomplete type 'struct S'
My question now is: Is this guaranteed behaviour which has some ruling in the standard or any other documents?
To be more precise about my question:
C
is a template class, whose members f()
and g()
are only instantiated when they are being referenced. f()
is referenced in main()
. If I do not reference g()
(which internally tries to use an incomplete type), the code would compile. But g()
is being referenced within an if-branch inside f()
. This branch is deterministically never being executed. So the compiler could potentially ignore/remove this dead code branch and thus avoid the instantiation of g()
(and with that the error of trying to use the incomplete type). However, this is not happening (on the compilers I tried at least).
I understand that allowing this would turn illegal code into legal code by merely adjusting the optimization settings of a compiler, but still my question is if this code example is guaranteed to fail due to some rules (e.g. order of optimization vs. template passes) which can be read about somewhere.
Thanks for any insights.