Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
507 views
in Technique[技术] by (71.8m points)

c++ - CRTP -- accessing incomplete type members

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:

  1. 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?

  2. 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...