C++模板编程(18)---模板实例化instantiation

Template实例化instantiation是由泛化的template定义式产生出实际类型和函数的过程。C++template实例化是一个基础而复杂的概念。说它复杂的一个原因是,由template产生的物体entities的定义不限于源码的某一单独位置上。template所在位置、template被使用位置、以及template argument定义位置,都在构成物体意义一事上扮演各自的角色。

本文·讲述如何组织我们的程序代码才能以正确方式运用template。我们还将讲述为解决实际实例化问题,大多数流行的C++编译器所使用的方法,尽管这些方法应该是语义等价的。

1. 随需实例化on-demand instantiation

    当C++编译器见到程序中使用一个template特化体specialization,便将template parameters替换为所需的argument,以创建出这个特化体。这个过程是自动完成,无需借助任何client程序码或template定义的指示。正是这种随需实例化的特性使得C++template机制有别于其它语言的类似机制。这种机制有时也称为隐式implicit或自动automatic实例化。

随需实例化意味着,当程序用到template时,编译器需要得知该template和其某些成员的完整定义(而不仅仅是template的声明)。考虑下面的例子:

template<typename T> class C;   // (1) 只有声明

C<int>* p=0;                             // (2) 没问题,不要 C<int> 的定义

template <typename T>

class C{

public:

        void f();                    // (3) 成员声明

};                                      // (4) class template定义完备

void g (C<int>& c)          //(5) 只用到class template的声明

{

        c.f();                     //(6) 用到了class template的定义:需要C::f()的完整定义

}

在(1)处,编译器只能见到template的声明,见不到其定义(这种声明又称为前置声明,forward declaration)。和常规classes的规则一样,不需要class template的定义,我们就可以定义给类型的指针pointer或引用reference,如这里的(2)。例如函数g()的参数类型C<int>&并不需要template C的完整定义。然而一旦编译器需要知道某个template特化体的大小或程序代码中取用了该特化体的某个成员,编译器就必须见到template的定义。这说明为什么在(6)处,class template的定义必须可见:如果见不到这个定义,编译器就无法确认这个成员是否存在,或程序代码是否有权取用它(必须不为private或protected,才能被取用)。

这里有另外一个表达式,需要class template实例化,因为此处编译器必须知道C<void>的大小。

C<void>* p = new C<void>;

这里必须完成实例化,这么一来编译器才知道C<void>的大小。你可能会注意到无论把template C的参数T以什么样的类型X替换,其template实例化的大小都不会受到影响:任何情况下C<X>都是个empty class。编译器也需要以实例化过程来得知C<void>是否一个可被取用的default构造函数,并确保C<void>没有定义private operator new 和 private operator delete。

有时候,从程序代码本身并不能看出某个class template的成员会被取用。例如C++的重载解析机制overload resolution便需要得知各候选参数的函数额class types:

template <typename T>

class C {

public:

        C(int);

};

void candidate(C<double> const&);  //(1)

void candiate(int) {}                           //(2)

int main()

{

        candidate(42);    //上面声明的两个函数都可被调用

}

编译器会将candidate(42)解析resolve为(2)的声明。然而(1)处的声明也可能被实例化,用来确定它是否也是上述调用的一个合法候选函数(本例之中实例化可能发生),因为42可隐寓通过单自变量构造函数转型为C<double>类型的 rvalue。

2.缓式实例化Lazy instantiation

3.C++实例化模型Instantiation Model

4.实现方案Implementation Schemes

5.显式实例化Explicit Instantiation

6.小结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值