I'd like a short clarification on how complete types relate to CRTP. I thought this question was somewhat related. However, my question here question pertains to CRTP where a derived class member function explicitly calls the base class member function, which in turn calls a derived function. This appears different from calling a base class function on a derived type once within the main routine.
I have also read this question where it was explained that the static constexpr
members of the base class that make use of the derived class are not initialized until the derived class is seen by the compiler and is complete. However in that case, the derived class was also templated.
Here is my question. Consider
template<typename D> struct B{
void foo() const { static_cast<const D*>(this)->baz(); }
};
struct D : B<D> {
void bar() const { foo(); }
void baz() const {}
};
As I understand, each D
remains an incomplete type until the closing brace of the class. I also understand that member function templates are not instantiated until they are used. Thus, if we ignore D::bar
for now, it makes sense that the following is valid in main:
D d; d.foo();
What I need further clarification about is what constitutes use? For example, in defining D::bar
, there is a call to B::foo
(so that function is presumably instantiated there) which would then require D
to be a complete type. But at the point where D::bar
is being defined, D
is not complete. Or is it?
I thought perhaps what could be happening is that where D::bar
is being defined and calls B::foo
, it forces the compiler to make a declaration for B::foo
(no definition required). And perhaps the definition does not happen until D::bar
is actually called at some other point. But I ran this at C++ Insights and became more confused as the explicit specialization of B
to B<D>
happens even before D
is declared. Clarification would be appreciated!