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

CRTP -- accessing incomplete type members

相关问题:one, two

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 }

问题是:

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

  2. 输入declaration/definition的顺序是什么?如我所见:

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

    b。第 11 行 -- 在 class Implementation 之后 -- Implementation 声明但未定义的类型。

    c。第 11 行——在 Interface<Implementation> 之后——模板实例化。由于步骤 (b),此时 Implementation 是已知的(但未定义!)。编译器 "injects" 代码用 IMPL 替换为 Implementation。在这里,以我的观点,第 7 行和第 8 行都不合法,因为在这一点上,编译器不知道 Implementation 有这些成员。它是怎么知道的?

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

我考虑得更多,对我所拥有的 C++ 类型基础知识的了解更少。任何澄清表示赞赏。

当一个class模板被实例化时,除了非虚拟成员函数之外的它的成员也被一起实例化。然而,非虚拟成员函数仅在使用 odr 时实例化(基本上,调用或获取其地址)。

当编译器遇到class Implementation : public Interface<Implementation>时,需要实例化Interface<Implementation>。此时,Implementation 仍然是一个不完整的类型,它的 TYPE 成员还没有出现。另一方面,Interface<Implementation>::foo 仅在稍后在 main 中调用时实例化。到那时,Implementation是一个完整的类型。