C++模板编程(19)---缓式实例化Lasy Instantiation

上文中所举例子中,都与non-template classes有本质上的区别。很多情况下编译器需要一个完整的class 类型。运用template时,编译器会从class template定义式中产生这个完整的定义。

这就引发一个相关问题:template之中有多少内容需要实例化?一个模糊的回答是:只有真正被用到的那些才需要被实例化。换句话说编译器应该尽量推迟templates实例化的进行,这便是所谓Lasy instantiation。

当class template 被隐式实例化,其中的每一个成员声明也都同时被实例化,然而并非所有对应的定义也都被实例化,其中有些例外。首先,如果class template内含有一个不署名的union,这个union的成员也都会被实例化。另一个例外与virtual 成员函数有关。当class template被实例化时,virtual 成员函数的定义可能被实例化。事实上很多编译器都会实例化这些定义。因为virtual call机制的内部结构要求:virtual 函数作为可链接物linkable entities,存在于某个结构(译注:vtbl/vptr)中。

当templates被实例化时default call arguments 通常被个别考虑除非有些调用真正用上了default arguments,否则那些default argument不会被实例化。如果调用函数时明确指定了arguments,那么default arguments也不会被实例化。

下面的例子,涵盖了上述内容:

template <typename T>

class Saft {

};

template <int N>

class Danger

{

public:

        typedef char Block[N];

};

template <typename T, int N>

class Tricky {

public:

        virtual ~Tricky() {}

        void no_body_here(Safe<T> = 3);

        void inclass() {

                Danger<N> no_boom_yet;

        }

        //void error() { Danger<0> boom; }

        //void unsafe(T (*p)[N]);

        T operator->();

        struct Nested

        {

               Danger<N> pfew;

        };

        union {

                int align;

                Saft<T> anonymous;

        };

};

int main()

{

        Tricky<int,0> ok;

}

首先考虑main()不存在的情况。符合标准的C++编译器通常会编译template定义式以进行语法检查,并进行一般的语义约束sematic constraints检查。然而在检查template parameters约束条件时,它会假设最好情况。例如Block内的typedef 的参数N有可能是0或负值(这是非法的),但编译器假设这种事情不会发生。类似情况,class template Tricky的成员函数no_body_here的声明语句中,预设自变量(=3)颇为可疑,因为template Safe无法以一个整数值初始化,但编译器会假定Safe<T>的泛化定义并不需要这个预设自变量。另外,如果不把成员函数 error()函数注释掉,它会引发一个错误,因为它会调用Danger<0> 特化体,而这个特化体试图 typedef 定义0个元素的数组Array。即使成员函数error()未被调用,这个错误也会在编译期对整个泛型template进行处理的时候触发。但成员函数unsafe(T(*p)[N]) 并没有这个问题,因为此时N还是个泛型参数,template parameter的替换并未发生。

    现在让我们分析main()存在的情况下。它会将template Tricky的参数T替换为int,参数N替换为0.编译器不需要所有成员的定义,但default构造函数(本例为隐寓声明,未写出)和析构函数一定会被调用,因此编译器必须见到它们的定义。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值