C++模板编程(15)---模板解析(Parsing Templates)

0.简介

    大多数编程语言编译器会进行两项基本任务:

    1)tokenization,又称为扫描scanning

     2)parsing分析,上面的tokenization步骤会把源码读入的一个字符序列characters sequence,

再由parsing,也就是词法分析器,在词汇单元序列中寻找已知的模式patterns。

1. NonTemplate的上下文敏感性(context Sensitivity)

    tokenizing要比Parsing容易,幸运的是parsing理论基础已经相当稳固,很多语言都可以根据这个理论不困难地进行parsing。这个理论对于上下文无关地语言最有效,然而C++是一个上下文敏感的语言。为了进行Parsing, C++编译器把一个符合表(symbol table)结合于tokenizer和parser身上:当某个声明被成功解析后,便进入符合表中。当tokenizer找到一个标识符identifier,便查询符号表,如果在其中找到对应(同名)类型,就将resulting token标注出来。

举个例子,如果C++编译器看到

x*

于是tokenizer查询x。如果在符合表中找到类型x,parser会看到

identifier, type,

x symbol, *

于是推断位一个声明的开始,然而如果x不是类型,那么parser会从tokenizer获得:

identifier, nontype,

x symbol, *

于是这个构件construct就只能被合法解析为一个乘法操作。这些原则的细节取决于具体操作策略,但要旨没变。

下面例子说明上下文敏感性context sensitivity。考虑以下表达式:

x<1>(0)

如果x是个class template名称,这个表达式便是将整数0转型为X<1>所指涉的类型。但如果X不是个template。这个表达式等价于:

(X<1 ) > 0

换句话说X和1的比较结果(true或false)被隐式转型为1或0,然后再与0比较。虽然这种写法很少见,但它确实是合法的C++程序代码。只有C++ parser看到一个template名称时,它才确实是合法C++代码。只有当 C++ parser看到一个template名称时,它才认为其后面跟的<是角括号,否则就当作小于号。

这种上下文敏感,是当初以角括号作为模板参数列表界定符合的不幸产物。下面是另一个例子:

template <bool B>

class Invert

{

 public:

        static bool const result = !B;

};

void g()

{

        bool test =  Invert<(1>0)>::result;

}

如果圆括号不存在,就会被编译器误认为非法算式。

2. 类型的受控名称Dependent Names

Templates内的名称,其问题在于:它们往往不具备足够的确定性。更明确地说,一个template不能窥见另一个模板template的内部,因为后者的内容可能因为明确特化(explicit specialization)而变得不合法。下面的例子可以说明这一点:

template <typename T>

class Trap{

public:

        enum {x}; // (1) x is not a type

};

template <typename T>

class Victim

{

public:

        int y;

        void proof()

        {

                Trap<T>::x * y;  // (2) 这是一个声明还是一个乘法算法?

        }

};

template <>

class Trap<void>    //恶意特化

{

public:

        typedef int x;   //(3) x is one type

};

void boom(Victim<void>& bomb)

{

        bomb.proof();

}

编译器对(2)进行parsing时,它必须确定是个声明还是乘法,而这取决于受控受饰名称dependent qualified name  Trap<T>::x是不是一个类型名称。但是这有个问题:

从(1)看Trap<T>::x不是类型,(2)是个乘法;

但从(3)来看Trap<T>::x 事实上成了int 类型。

C++对此问题做了明确规定:通常一个受控受饰名称dependent qualified name并不指涉某个类型,除非该名称以关键词typename为前导。

3. 模板的受控名称Dependent Names

4 Using声明语句中的受控名称Dependent Names

5. ADL和 显式模板实参Explicit Template Argument

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值