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)
问题是:
为什么我可以从IMPL::
(第8行)调用函数但不能访问类型文件(第7行)?在相关问题中,据说这IMPL
是一个不完整的类型.但为什么第8行是正确的呢?
什么是类型声明/定义的顺序?照我看来:
一个.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
是一个完整的类型.