文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-06-17 08:05

关注

本篇内容主要讲解“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<int, vector<int>>

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

map<int, vector<int> >

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

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

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

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

 

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).&mdash;end note ]

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

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

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

Foo<(3>>1)> foo;

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯