When a class template is instantiated, its members other than non-virtual member functions are instantiated together with it. Non-virtual member functions, however, are only instantiated when odr-used (basically, called or have their address taken).
When the compiler encounters class Implementation : public Interface<Implementation>
, it needs to instantiate Interface<Implementation>
. At this point, Implementation
is still an incomplete type, its TYPE
member has not yet been seen. On the other hand, Interface<Implementation>::foo
is only instantiated later, when it’s called in main
. At that point, Implementation
is a complete type.