CRTP - 访问不完整类型的成员

Dim*_*imG 5 c++ crtp incomplete-type c++11

相关问题:,

在尝试了解CRTP几天后,似乎现在我比以前更了解:)

请考虑以下代码:

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 }
Run Code Online (Sandbox Code Playgroud)

问题是:

  1. 为什么我可以从IMPL::(第8行)调用函数但不能访问类型文件(第7行)?在相关问题中,据说这IMPL是一个不完整的类型.但为什么第8行是正确的呢?

  2. 什么是类型声明/定义的顺序?照我看来:

    一个.Interface模板 - 好的.在实例化之前不会带来任何问题

    湾 第11行 - 后class Implementation- Implementation类型声明但未定义.

    C.第11行Interface<Implementation>- 模板实例化后.Implementation由于步骤(b),此时已知(但未定义!).编译器"注入" IMPL替换为的代码Implementation.在我看来,第7行和第8行都不合法,因为此时编译器不知道Implementation有这些成员.它怎么知道呢?

或者实例化真的可以在第21行?但在那种情况下为什么07行不起作用?

我想的更多,对我所拥有的C++类型基础知识的理解较少.任何澄清表示赞赏.

Igo*_*nik 11

实例化类模板时,非虚拟成员函数以外的成员将与其一起实例化.但是,非虚拟成员函数仅在使用odr时被实例化(基本上,被调用或具有其地址).

当编译器遇到时class Implementation : public Interface<Implementation>,它需要实例化Interface<Implementation>.此时,Implementation仍然是一个不完整的类型,其TYPE成员尚未见过.另一方面,Interface<Implementation>::foo只有在它被调用时才会被实例化main.那时,Implementation是一个完整的类型.

  • 将附加参数传递给“Interface”,如“Implementation : public Interface&lt;Implementation, int&gt;”中所示。从该参数中获取“Interface” typedef“TYPE”,那么“Implementation”就不需要了。 (2认同)