On-Demand实例化

当C++编译器遇到模板特化的时候,他会利用所给的实参替换对应的模板参数,从而产生该模板的特化。该过程是自动进行的。有时候也会被称为隐式实例化,或者是自动实例化。

on-demand实例化表明:在使用模板(特化)的地方编译器通常需要访问模板某些模板成员的整个定义(也就是说只有声明是不够的)考虑下面的代码。

   1:  template<typename T> class C; //声明而已
   2:  C<int >* p = 0; //这里只要声明就够了,因为这里没有new一个实例
   3:   
   4:  template<typename T>
   5:  class C{
   6:  public:
   7:  void f();//成员函数声明
   8:  };
   9:   
  10:  void g(C<int>& c)//这里只需要类模板的声明
  11:  {
  12:   c.f();//这里用到了f的定义
  13:  }

记住如果某个组件需要知道模板特化后的大小,或者访问该特化的成员,那么整个类模板的定义就需要位于可见区域中。因为如果编译器看不见的话,编译器就不能确定这个类中是否含有改成员函数,是否可以被访问到。

延迟实例化

当隐式实例化类模板时,同时也实例化了该模板的每个成员的声明,但并没有实例化相应的定义。

当实例化模板的时候,缺省的函数调用实参是分开考虑的。如果这个函数不使用缺省的实参而是显示的实参来进行调用的那么就不会实例化缺省实参。

然而也存在一些例外的情况,首先,如果类模板中包含了一个匿名的union,那么该模板实例化结果,union定义的成员同时被实例化。另一种情况,如果含有虚函数,虚函数的定义可能被实例化但也可能没有被实例化。这要依据具体的实现,实际上,许多实现都会被实例化虚函数这个定义,因为“实现虚函数调用机制的内部结构”要求虚函数的定义做为链接的实体存在

   1:  template<typename T>
   2:  class Safe{
   3:  };
   4:  template<int N>
   5:  class Danger{
   6:  public:
   7:  typename char Block[N]; 
   8:  };
   9:   
  10:  template <typename T, int N>
  11:  class Tricky{
  12:  public:
  13:  virtual ~Tricky(){}
  14:   
  15:  void no_body_here(Safe<int> = 3);
  16:   
  17:  void inclass(){
  18:  Danger<N> no_boom_yet; 
  19:  }
  20:   
  21:  //void error(){ Danger<0> boom; }
  22:  //void unsafe(T (*p)[N]);
  23:   
  24:  T operator->();
  25:  //virtual Safe<T> suspect();
  26:   
  27:  struct Nested{
  28:  Danger<N> pfew;
  29:  };
  30:  union {
  31:  int align;
  32:  Safe<T>anonymous;
  33:  };
  34:  };
  35:   
  36:  int main()
  37:  {
  38:  Tricky<int, 0> ok;
  39:  }

再涉及到模板参数的约束时,编译器会假设该参数处于最理想的情况。例如,他会假设void no_body_here(Safe<int> = 3);不会用到隐式参数,他会假设typename char Block[N]; 中的N不是0或者是小于0的数。

如果编译main()函数,那么有哪些表达是不合法的

  18:Danger<N> no_boom_yet; //数组元素个数不能为0
  28: Danger<N> pfew;//数组元素个数不能为0
以上的虽然表达不合法,但是当是他们都是位于定义中,所以都没有用到所以可以被编译通过。
再来看一下备注释掉的,如果没有被注释掉的话,
  25:  //virtual Safe<T> suspect();
因为是虚函数所以会被实例化,但是没有函数体的定义。
22: //void unsafe(T (*p)[N]);
因为会被声明所以参数中会定义元素个数为0的数组,编译不通过。
  21:  //void error(){ Danger<0> boom; }
在编译期间就会产生出错,被检查到了。
 
那么18和19中的Danger<N> 和 21中的Danger<0>中在编译时有什么区别,在没有被main中的0实例化时,
编译器会假设18和19中的Danger<N>中的N是合法的,而21中的Danger<0>是不合法的,这就叫延迟实例化
 

C++模板实例化(1)的更多相关文章

  1. C++模板实例化

    深入理解C++中第七章提到模板实例化参数的选择:函数的决议结果只和函数参数有关和返回值无关.记录一下. 测试程序如下: #include <iostream> using namespac ...

  2. c++模板实例化的一个例子

    以下是c++模板实例化的一个例子,虽然ObjectList::clear()里面调用的test()函数是没有定义的,但是以下代码能够编译通过,可见ObjectList::clear()未编译: tem ...

  3. SQL模板和模板实例化

    需求:需要得出一个数据源DataTable,我已知SQL和HttpRequest如何,通过SQL模板的方式去实例化匹配HttpRequest中的参数实例化为查询SQL,最后返回DataTable 1. ...

  4. C++模板之函数模板实例化和具体化

    模板声明 template<typename/class T>,  typename比class最近后添加到C++标准. 常规模板,具体化模板,非模板函数的优先调用顺序. 非模板函数(普通 ...

  5. C++ Primer 学习笔记_77_模板与泛型编程 --实例化

    模板与泛型编程 --实例化 引言: 模板是一个蓝图,它本身不是类或函数.编译器使用模板产生指定的类或函数的特定版本号.产生模板的特定类型实例的过程称为实例化. 模板在使用时将进行实例化,类模板在引用实 ...

  6. 如何导出标准模板库(STL)类的实例化和包含STL类对象数据成员的类

    本文翻译自 https://support.microsoft.com/zh-cn/help/168958/how-to-export-an-instantiation-of-a-standard-t ...

  7. C++ template —— 实例化和模板实参演绎(四)

    本篇讲解实例化和模板实参演绎-------------------------------------------------------------------------------------- ...

  8. C++模板之隐式实例化、显示实例化、隐式调用、显示调用和模板特化详解

    模板的实例化指函数模板(类模板)生成模板函数(模板类)的过程.对于函数模板而言,模板实例化之后,会生成一个真正的函数.而类模板经过实例化之后,只是完成了类的定义,模板类的成员函数需要到调用时才会被初始 ...

  9. 使用 c++ 模板显示实例化解决模板函数声明与实现分离的问题

    问题背景 开始正文之前,做一些背景铺垫,方便读者了解我的工程需求.我的项目是一个客户端消息分发中心,在连接上消息后台后,后台会不定时的给我推送一些消息,我再将它们转发给本机的其它桌面产品去做显示.后台 ...

随机推荐

  1. 用Systemtap探索MySQL

    http://www.actionsky.com/docs/archives/168#Systemtap 目录 1 Systemtap 2 Systemtap 观测点的支持程度 2.1 官方编译的My ...

  2. Linux五种IO模型

    http://www.cnblogs.com/renxs/p/3683189.html

  3. mysql基本定义--数据类型

    浮点数类型与定点数类型: MySQL中使用浮点数类型和定点数类型来表示小数. 浮点数类型包括单精度浮点数(float型)和双精度浮点数(double型).定点数类型就是decimal型. OK,现在我 ...

  4. IOS 区分缓存 内存 物理存储 逻辑存储

    1. 存储器分为内部存储器(内存)和外部存储器(外存). ①内存 内存是电脑内部临时存放数据的地方,供CPU直接读取,存放在其中的数据要靠电来维持,一旦断电就会丢失.因此,在操作电脑时,应及时地将需要 ...

  5. Java基础知识强化之多线程笔记06:Lock接口 (区别于Synchronized块)

    1. 简介 我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式 ...

  6. C++: byte 和 int 的相互转化

    原文链接:http://blog.csdn.net/puttytree/article/details/7825709 NumberUtil.h // // NumberUtil.h // MinaC ...

  7. Oracle基础 物理备份 冷备份和热备份(转)

    一.冷备份介绍:    冷备份数据库是将数据库关闭之后备份所有的关键性文件包括数据文件.控制文件.联机REDO LOG文件,将其拷贝到另外的位置.此外冷备份也可以包含对参数文件和口令文件的备份,但是这 ...

  8. yum中baserul路径中的空格

    配置yum源时,比如指定本地挂载的光盘时,路径中包含空格.在不使用链接的情况下,用"\"进行转义不行,把路径加单.双引号也不可行.正确做法是把空格用%20代替.同理,其他不可识别的 ...

  9. 人体时钟hone hone clock

    摘要:一个由日本人设计的有意思的Flash时钟:人体时钟 hone hone clock .安装很简单,直接js导入即可,包括两种样式:透明背景和白色背景. 很可爱的一个设计,实现后效果如下: 使用方 ...

  10. log4net日志文件名输出格式化

    日志文件输出格式: 20130626.txt20130627.txt20130628.txt20130629.txt <appender name="rolling" typ ...