千家信息网

C++模板>>编译问题举例分析

发表于:2024-11-11 作者:千家信息网编辑
千家信息网最后更新 2024年11月11日,本篇内容主要讲解"C++模板>>编译问题举例分析",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C++模板>>编译问题举例分析"吧!在编译理论中,通常将编译
千家信息网最后更新 2024年11月11日C++模板>>编译问题举例分析

本篇内容主要讲解"C++模板>>编译问题举例分析",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C++模板>>编译问题举例分析"吧!

在编译理论中,通常将编译过程抽象为5个主要阶段:词法分析(Lexical Analysis),语法分析(Parsing),语义分析(Semantic Analysis),优化(Optimization),代码生成(Code Generation)。这5个阶段类似Unix管道模型,上一个阶段的输出作为下一个阶段的输入。其中,词法分析是根据输入源代码文本流,分割出词,识 别类别,产生词法元素(Token)流,如:

int a = 10;

经过词法分析会得到[(Type, "int"), (Identifier, "a"), (AssignOperator, "="), (IntLiteral, 10)],在后续的语法分析阶段,就会根据这些词法元素匹配相应的语法规则。在我学习编译原理时,教科书中对于词法分析的介绍主要是基于正则表达式的,言 下之意就是普通语言的词法规则是可以通过正则表达式描述的。比如,C语言的变量名规则是"包含字母、数字或下划线,并且以字母或下划线开头",这就可以用 正则表达式[a-zA-Z][a-zA-Z0-9]*表达。但是,在实践中我发现不管是主流语言,还是自己设计的DSL都大量存在不能简单通过正则表达式进行词法分析的例子。来看C++98的模版例子:

map>

上面这段代码会被C++98编译器中报语法错误,原因在于它把">>"识别成了位右移运算符而不是两个模版右括号,在C++98中必须在两个括号中间加空格,写成

map >

除此了C++模版,据我所知,经典的FORTRAN语言的语法规则更是大量存在词法歧义。

我认为从本质上讲,这类问题的根源在于词法分析的依据只是简单的词法规则,并不具备所有的语法信息,而词法歧义必须提升一层在语法规则中消除。所 以,在我自己设计一些DSL的时候干脆就把词法分析和语法分析合二为一了,相当于让语法分析在字符层次上去进行,而不是经典的词法元素层次上,这就是所谓 的Scannerless Parsing。采用这种方法的例子并不少见,TeX, Wiki, Makefile和Perl 6等语言的语法分析器都属此类。

Scannerless Parsing方法弥补了词法规则无法消歧的问题,但是同时也破坏了词法和语法分析简单清晰的管道结构,总体上增加了实现和理解的复杂度。另外,像C++ 这样大型的语言,如果开始是有词法分析的,稍微碰到一个歧义就整个转成Scannerless Parsing未免也显得太夸张了。这个问题困扰了我很久,直到最近才找到了一个满意的解决方案。还是以上面">>"为例,我们知道现在 C++11已经允许不加空格了,那么C++11编译器是如何处理这个词法歧义的呢?答案是:词法分析阶段既然分析不好">>",干脆就不分析 了,直接把">" ">"交给语法分析器来分析,其他没有词法歧义的照旧。当我知道这个方案的时候不由得感叹:妙!理论上,词法分析是可以什么也不做的,全部把字符一 一交给语法分析器也没有问题,所以,干脆让词法分析只做有把握的部分,解决不了的交给语法分析器,这样就既保留了管道结构,又解决了词法歧义。

下面我们再来看看C++11规范关于这个问题的定义:


14.2 Names of template specializations [temp.names] ###

After name lookup (3.4) finds that a name is a template-name or that an operator-function-id or a literal-operator-id refers to a set of overloaded functions any member of which is a function template if this is followed by a <, the < is always taken as the delimiter of a template-argument-list and never as the less-than operator. When parsing a template-argument-list, the first non-nested > is taken as the ending delimiter rather than a greater-than operator. Similarly, the first non-nested >> is treated as two consecutive but distinct > tokens, the first of which is taken as the end of the template-argument-list and completes the template-id. [ Note: The second > token produced by this replacement rule may terminate an enclosing template-id construct or it may be part of a different construct (e.g. a cast).—end note ]

可见,在C++11中,词法分析器是把">>"直接当成两个">"传给了语法分析器,然后在语法分析中如果匹配了template- argument-lis语法,***个">"符号会被直接认为是模版结束符,而不是大于,也不是位移符号。根据这个定义,我构造了一个例子:

template class Foo { };   Foo<3>>1> foo;

这个例子在C++98中是能正确编译的,">>"被解释成了位移运算,但是它反而不能在C++11中编译了,因为根据规范***个">"被解释成了模版参数结束符。如果要在C++11中编译,需要显式地加上括号:

Foo<(3>>1)> foo;

到此,相信大家对"C++模板>>编译问题举例分析"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

分析 词法 语法 编译 问题 规则 分析器 歧义 语言 阶段 C++ 例子 模版 正则 表达式 模板 两个 元素 括号 方法 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 假期景区网络安全宣传 黑魂3什么时候开启服务器 东郊租房软件开发 怎么学习好一点的网络技术 兰石化网络技术 微信为什么连接不到服务器 域管理可以不设域控服务器吗 数据库访问监控技术的优点 山西戴尔服务器续保维护 主视频服务器控制端口是什么 DOE全球储能数据库网址 我的小米云服务器 数据库原理怎样求f的最小集 mysql有哪两种数据库 web软件用什么数据库 搭建ftp服务器工具 陌陌不能连接到服务器 ntp时间同步服务器 阿里 实现简单的界面与数据库的交互 上海软件开发设施有哪些 高青企业管理软件开发定制开发 黑客网络安全之密码学基础 网信办网络安全态势感知平台 牧原集团的软件开发岗怎么样 昆明软件开发培训学校多少钱 枣庄移动网络安全 车载网络技术应用的作用 群晖服务器错误代码 局网络安全人员管理制度 收费app需要数据库
0