[英]Incomplete type while accessing templated derived class (CRTP)' static function while doing SFINAE
[英]CRTP -- accessing incomplete type members
在尝试了解 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 }
问题是:
为什么我可以从IMPL::
:(第 8 行)调用函数,但不能访问类型文件(第 7 行)? 在相关问题中,据说IMPL
在这一点上是不完整的类型。 但是为什么第 8 行是正确的?
类型声明/定义的顺序是什么? 照我看来:
一种。 Interface
模板——好的。 在实例化之前不会带来任何问题
湾第 11 行——在class Implementation
——已声明但未定义的Implementation
类型。
C。 第 11 行——在Interface<Implementation>
——模板实例化。 在这一点上,由于步骤 (b), Implementation
已经是已知的(但没有定义!)。 编译器“注入”带有IMPL
代码,替换为Implementation
。 在这里,在我看来,第 7 行和第 8 行都不合法,因为此时编译器不知道Implementation
具有这些成员。 它怎么知道比?
或者实例化真的发生在第 21 行? 但在那种情况下,为什么第 7 行不起作用?
我想得更多,我对 C++ 类型基础知识的理解较少。 任何澄清表示赞赏。
当一个类模板被实例化时,它的非虚成员函数以外的其他成员也一起被实例化。 然而,非虚拟成员函数仅在 odr 使用(基本上,调用或获取其地址)时才被实例化。
当编译器遇到class Implementation : public Interface<Implementation>
,需要实例化Interface<Implementation>
。 此时, Implementation
仍然是一个不完整的类型,它的TYPE
成员还没有被看到。 另一方面, Interface<Implementation>::foo
仅在稍后在main
调用时实例化。 此时, Implementation
是一个完整的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.