The following is invalid code:
struct foo {
struct bar;
bar x; // error: field x has incomplete type
struct bar{ int value{42}; };
};
int mai
I am not sure that the accepted answer is the correct explanation, but it is the most plausible one for now. Extrapolating from that answer, here are the aswers to my original questions:
template
) considered invalid? If the compiler can figure out the second option, I don't see a reason why it wouldn't be able to figure out the first one. [ Because C++ is weird - it handles class templates differently than classes (you could have probably guessed this one). ]When instantiating foo{}
in main
the compiler instantiates an (implicit) specialization for foo_impl
. This specialization references foo_impl
on line 4 (bar x;
). The context is within a template definition so it depends on a template parameter, and the specialization foo_impl
is obviously not previously instantiated, so all the preconditions for [temp.point]/4 are fulfilled, and the compiler generates the following intermediate (pseudo)code:
template
struct foo_impl {
struct bar;
bar x; // no problems here
struct bar{ int value{42}; };
};
using foo = foo_impl<>;
// implicit specialization of foo_impl::bar, [temp.point]/4
$ struct foo_impl::bar {
$ int value{42};
$ };
// implicit specialization of foo_impl
$ struct foo_impl {
$ struct bar;
$ bar x; // bar is not incomplete here
$ };
int main() { return foo{}.x.value; }
As per [temp.spec]/4:
A specialization is a class, function, or class member that is either instantiated or explicitly specialized.
so the call to foo{}.x.value
in the original implementation with templates qualifies as a specialization (this was something new to me).
The version with explicit specialization does not compile as it seems that:
if the context from which the specialization is referenced depends on a template parameter
no longer holds, so the rule from [temp.point]/4 does not apply.