I must be missing something really obvious here. Consider two examples below:
struct Test;
int bar()
{
return sizeof(Test); // (1), compilation error: Test is incomplete
}
struct Test
{
char x[123456];
};
The first example cannot be compiled for obvious reason: struct Test
is incomplete at line marked (1)
and hence any expression that requires complete type would fail. That's understandable.
template <typename T>
int foo()
{
return sizeof(T);
}
struct Test;
int bar()
{
return foo<Test>(); // (2): no error.
}
struct Test
{
char x[123456];
};
However, this second example compiles just fine and that surprises me a lot.
My naiive understanding of implicit template instantiation suggested that foo<Test>()
is instantiated at line marked (2)
and that class Test
is still incomplete at that point. Which made me think that applying sizeof
operator to it would result in the same compilation error.
Godbolt proves me wrong even with --std=c++98
-- generated assembler code shows that foo<> returns correct value, and another godbolt dashboard (thanks, Marek R!) shows that this example seems valid across several compilers and standard options. I can't figure out why... So my questions are:
Does that second code snippet constitute a well-formed program according to C++17 standard?
What is the point of instantiation of function
foo<Test>()
?Why is
Test
treated as a completely defined class in the body of instantiatedfoo<>()
?
Edit:
The question linked as a duplicate asked a different question. It asked: "is the compiler conforming?" and the answer was: "yes, the compiler is allowed to do that". This question, on the contrary, asks: "is the code well-formed?" (see question #1 above) and the answer, judging by the comments, seems to be "no, it's ill-formed".