CRTP — accessing incomplete type members

陌路散爱 提交于 2019-12-21 17:19:58

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/35428422/crtp-accessing-incomplete-type-members

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!