当前位置: 首页 > news >正文

网站开发维护印花税重庆市万州建设工程信息网

网站开发维护印花税,重庆市万州建设工程信息网,万网网站后台,网站阿里云备案要多久目录 14.1 On-Demand实例化 14.2 延迟实例化 14.2.1 部分实例化和完整实例化 14.2.2 实例化组件 14.3 C实例化模型 14.3.1 两阶段查找 14.3.2 POI 14.3.3 包含式模型 14.4 几种实现方案 14.4.1 贪婪实例化 14.4.2 查询实例化 14.4.3 迭代实例化 参考#xff1a;…目录 14.1 On-Demand实例化 14.2 延迟实例化 14.2.1 部分实例化和完整实例化 14.2.2 实例化组件 14.3 C实例化模型 14.3.1 两阶段查找 14.3.2 POI  14.3.3 包含式模型 14.4 几种实现方案 14.4.1 贪婪实例化 14.4.2 查询实例化 14.4.3 迭代实例化  参考cpp-templates-2nd/第14章 实例化.md at master · r00tk1ts/cpp-templates-2nd (github.com) C模板实例化的概念非常基础但有时又错综复杂。这一复杂性的其中一个底层原因在于模板生成的实体定义不再局限于源代码单一的位置。模板本身的位置、模板使用的位置以及模板实参定义的位置均在实体的含义中扮演着重要角色。 14.1 On-Demand实例化 on-demand:请求式、按需、点播。 当C编译器遇到模板特化的使用时它会用需要的实参来替换模板参数来生成特化体。这一过程是自动完成的不需要客户端代码来引导或者不需要模板定义来引导。这一”on-demand“实例化特性使得C与其他早期的编译型语言的类似功能大相径庭如Ada或Eiffel其中的一些语言需要显式地实例化引导另外一些使用运行时分发机制来避免编译期实例化过程。有时这也被称作”隐式(implicit)实例化“或者”自动(automatic)实例化“。 On-demand实例化意味着编译器常常需要访问模板完整的定义换句话说不只是声明以及某些成员。考虑下面这一段精简的源码文件 templatetypename T class C; // #1 declaration only Cint* p 0; // #2 fine: definition of Cint not neededtemplatetypename T class C{public:void f(); // #3 member declaration }; // #4 class template definition completedvoid g(Cint c) // #5 use class template declaration only {c.f(); // #6 use class template definition; } // will need definition of C::f() // in this translation unittemplatetypename T void CT::f() // required definition due to #6 { } 另一个需要类模板实例化的表达式如下所示这里需要Cvoid实例化是因为它需要该类型的尺寸 Cvoid* p new Cvoid; 本例中需要实例化来保证编译器可以确定Cvoid的尺寸该new表达式需要去确认要分配多少存储空间。你可能会发现对这一模板来说替换模板参数T的实参X的类型无论是什么都不会影响模板的尺寸毕竟CX是一个空类没有成员变量或虚函数。然而编译器并不会通过分析模板定义来避免实例化所有编译器实际上都会进行实例化。 在源代码中是否需要访问类模板的成员并不总是那么直观。例如C重载决议规则要求如果候选函数的参数是类类型那么该类类型就必须是可见的 templatetypename T class C {public:C(int); // a constructor that can be called with a single parameter }; // may be used for implicit conversionsvoid candidate(Cdouble); // #1 void candidate(int) { } // #2int main() {candidate(42); // both previous function declarations can be called } 调用candidate(42)会采用#2处的声明。然而在#1处的声明也会被实例化来检查对于这个调用来说它是否是可用的候选者这个例子中由于模板的单实参构造器可以把42隐式转换成一个类型为Cdouble的右值。请注意如果模板不经实例化也可以找到调用函数合适的候选编译器还是被允许但不强制执行该实例化上例的情景中由于有精准匹配的候选者隐式转换的那个不会被选择。 14.2 延迟实例化 现在有一个相关问题模板实例化的程度如何可以给出这样的模糊答案会实例化到它实际需要的程度。换句话说编译器在实例化模板时应该是“懒惰”的。 14.2.1 部分实例化和完整实例化 如我们之前所见编译器有时不需要替换类或函数模板的完整定义。例如 templatetypename T T f(T p) { return 2*p; } decltype(f(2)) x 2; 本例中decltype(f(2))所指示的类型并不需要函数模板f()的完整实例化。编译器因此只被允许替换f()的声明而不是替换整个“身体”。这有时被称为部分实例化(partial instantiation)。 同样如果引用类模板的实例而不需要将该实例作为完整类型则编译器不应对该类模板实例执行完整的实例化。考虑下面的例子 templatetypename T class Q {using Type typename T::Type; };Qint* p 0; // OK: the body of Qint is not substituted 在这里Qint完整的实例化会触发一个错误因为在T是int类型时T::Type并没有意义。但是因为本例并不需要完整的Qint所以不会执行完整实例化代码也是OK的(尽管可疑)。 14.2.2 实例化组件 当类模板隐式完整实例化时其所有成员的声明也都会进行实例化但是对应的定义却并不会实例化即成员是部分实例化的。对此有一些特殊情况首先如果类模板包含一个匿名的联合体(union)该联合体的成员的定义也会实例化另一个特殊的情况出现在虚成员函数场景中它们的定义作为模板实例化的结果可能会也可能不会进行实例化。实际上许多实现都会实例化该定义因为“实现虚函数调用机制的内部结构”需要虚函数有一个链接实体存在。 14.3 C实例化模型 模板实例化就是从对应的模板实体通过合适地模板参数替换来得到一个常规的类型、函数或是变量的过程。这可能听起来直截了当但实际上需要遵循非常多的细节。 14.3.1 两阶段查找 在第13章中我们曾看到依赖型名称无法在解析模板时被找到。取而代之的是它们会在实例化的时刻再次进行查找。非依赖型名称则会在更早的阶段被查找因此当模板第一次看到它的时候就可以诊断出许多错误。这就引出了“两阶段查找”的概念。第一阶段查找发生在解析模板的时候而第二阶段查找发生在模板实例化的时候 在第一阶段当解析模板时非依赖型名称会并用一般查找规则和ADL规则如果可行的话。非限定依赖型名称诸如函数调用中的函数名称它们之所以是依赖型名称是因为它们具有依赖型实参会使用普通查找规则但是这一查找结果并不会作为最终结果而是要等到第二阶段的另一个查找过程完成也就是模板实例化的时候。在第二阶段此时的模板实例化被称作POI(point of instantiation)依赖型限定名称会在此时被查找对选定的实例用模板实参替换模板参数而且还会对非限定依赖型名称进行额外的ADL查找它们曾在第一阶段进行过普通查找。 14.3.2 POI  如上所述C编译器会在模板客户端代码的某些位置访问模板实体的声明或者定义。当某些代码结构引用了模板特化而且为了生成该特化需要实例化相应的模板定义时就会在源代码中产生一个POI。POI是源代码中的一个点在这里会插入已被替换的模板。例如 class MyInt {public:MyInt(int i); };MyInt operator - (MyInt const);bool operator (MyInt const, MyInt const);using Int MyInt;templatetypename T void f(T i) {if(i 0) {g(-i);} }// #1 void g(Int) {// #2fInt(42); // point of call// #3 } // #4 C编译器看到fInt(42)时它知道模板f需要用MyInt替换T来实例化这就产生了一个POI。#2和#3与该调用点紧邻但是它们都不适合做POI因为C不允许我们在这里插入::fInt(Int)的定义。此外#1和#4两处的本质区别在于在#4处函数g(Int)是可见的因此模板依赖的调用g(-i)可以在#4处被解析。然而如果我们假定#1是POI的话那么调用g(-i)将不能被解析因为g(Int)在#1处是不可见的。幸运的是对于函数模板特化的引用C把它的POI定义置于紧跟在“包含这个引用的定义或声明所在的最近的命名空间作用域”之后。在我们的例子中这个位置就是#4。 变量模板POI的处理与函数模板相似。而对于类模板特化来说情况则不太一样如下例所示 templatetypename T class S {public:T m; };// #1 unsigned long h() {// #2return (unsigned long)sizeof(Sint);// #3 } // #4 老规矩#2和#3都不能作为POI这两个位置不能进行命名空间作用域类Sint的定义模板是不能出现在函数作用域内部的。假如我们可以遵循函数模板实例的规则POI将会出现在位置#4处然而这样一来表达式sizeof(Sint)是无效的这是因为Sint的尺寸直到#4之后才能被确定。因此生成的类模板实例的引用被紧邻地定义在包含该引用的声明或定义的命名空间作用域之前。在我们的例子中这个位置就是#1。 14.3.3 包含式模型 当遇到POI时对应模板的定义必须是可访问的。对类特化来说这意味着类模板定义必须在编译单元中被更早地看见。而对函数模板和变量模板以及类模板的成员函数和静态数据成员的POI来说也同样需要。典型的模板定义被简单的通过#include语句引入到编译单元尽管是非类型模板也一样。这种模板定义的源码模型被称为包含式模型它目前是当下C标准所支持的模板的唯一自动源码模型。 14.4 几种实现方案 14.4.1 贪婪实例化 贪婪实例化假定链接器会意识到特定的实体尤其是可链接的模板实例化体它们大多在多个目标文件和库中重复出现。编译器会以一种特殊的方式标记这些实体。当链接器发现了多个实例时它会保留单个并丢弃掉所有其他的。这就是贪婪实例化的处理方法。 14.4.2 查询实例化 在这一方案中程序中参与的所有编译单元会汇集一个共享的数据库。该数据库可以追溯哪些特化体被实例化了并且可以找到其所依赖的源代码。生成的特化体本身会把信息存储在数据库中。当可链接实体遇到一个POI时会进入下面的处理流程 尚无可用的特化体这种情况会进行实例化特化的结果会保存到数据库中。特化体虽可用但超期了因为自它生成以来源代码发生了变化。这种情况同样会进行实例化新的特化结果会覆盖数据库中旧的那一个。数据库中有最新可用的特化体。这种情况什么都不用做。 14.4.3 迭代实例化  Cfront的迭代过程如下所述 编译源代码此时不要实例化任何需要链接的特化体使用预链接器(prelinker)链接目标文件预链接器调用链接器解析错误信息判断是否缺少某个实例化体。如果缺少的话预链接器会调用编译器来编译包含所需模板定义的源代码然后可选地生成该缺少的实例化体。重复第3步直到不再生成新的定义。 第3步中这种迭代的要求基于这样的事实在实例化一个可链接实体过程中可能会要求”另一个仍未实例化“的实体进行实例化最后所有的迭代都已经完成链接器才会成功创建一个完整的程序。
http://www.zqtcl.cn/news/539368/

相关文章:

  • 做网站客户会问什么问题手机如何制作网页链接
  • 做足球直播网站wordpress筛选框
  • 做网站需求文档深圳站建在边境
  • 网站建设法规浙江建设信息港证书查询
  • 影视作品网站开发与设计网站建设教程简笔画
  • 自己可以给公司做网站吗网站建设 用ftp上传文件
  • 电子商务网站开发与管理网站建设的设备
  • 网站建设项目公司沈阳网站关键字优化
  • 可以做淘宝联盟的免费网站优质国外网站
  • 石家庄营销型网站建设公司服装公司网站源码
  • 网站开发的软硬件需求做网站盘锦
  • 创意网站建设排行榜python和php哪个做网站
  • 开锁做网站怎么样榆林网站开发公司
  • 松原市建设局网站苏州网站建设-中国互联
  • 标书制作教程视频网站福田祥菱v1单排
  • 点网站出图片怎么做能看人与动物做的网站
  • 免费开源建站系统源码wordpress公共函数在哪里
  • 西昌市建设工程管理局网站模块化网站开发
  • 无限看片的视频大全免费下载上海网络优化方法
  • 物流公司做网站注重什么问题中国建设银行征信中心网站
  • 教务处网站建设专业做鞋子的网站吗
  • 梦幻创意网站建设成都做网站设计哪家便宜
  • 织梦网站栏目修改教程丝绸之路网站建设意义
  • 如何知道一个网站是谁做的北京装饰公司前十名
  • 杭州网站建设哪个平台好visualstudio 做网站
  • 广州站是哪个站h5建站系统
  • 网站首页网址应该有对应的域名南京高端模板建站
  • 自己做的网站竞价优化怎么做网站流量赚钱吗
  • 人力资源网站建设mip网站模板
  • 太原市住房和城乡建设部网站网站 备案 换空间