Related questions: one, two
After trying to understand CRTP for several days it seems that now I understand even less than before:)
Consider the following code:
01 #include <iostream>
02
03 template <class IMPL>
04 class Interace
05 {
06 public:
07 typedef typename IMPL::TYPE TYPE; // ERROR: "...invalid use of incomplete type..."
08 void foo() { IMPL::impl(); } // then why does this work?
09 };
10
11 class Implementation : public Interface<Implementation>
12 {
13 public:
14 typedef int TYPE;
15 static void impl() { std::cout << "impl() " << std::endl; }
16 };
17
18
19 int main()
20 {
21 Implementation obj;
22 obj.foo();
23 }
The questions are:
Why I can call function from IMPL::
(line 8) but cannot access type fileds (line 7)? In related question it is said that IMPL
is an incomplete type at this point. But why then line 8 is correct?
What it the order of type declaration/definition? As I see it:
a. Interface
template -- OK. Doesn't bring any problems until instantiating
b. line 11 -- after class Implementation
-- Implementation
type declared but not defined.
c. line 11 -- after Interface<Implementation>
-- template instantiation. At this point Implementation
is already known (but not defined!) due to step (b). Compiler "injects" code with IMPL
replaced with Implementation
. Here, to my point of view, neither line 7, neither line 8 are not legal because at this point, compiler doesn't know that Implementation
has these members. How does it knows than?
Or maybe Instantiation really goes at line 21? But in that case why line 07 doesn't work?
More I think about it, less understanding of C++ type fundamentals I have. Any clarification is appreciated.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…