You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
zhangyachen
changed the title
c++11-17 模板核心知识(十四)—— 解析模板之依赖型模板名称(.template/->template/::template)
c++11-17 模板核心知识(十四)—— 解析模板之依赖型模板名称 Dependent Names of Templates(.template/->template/::template)
Dec 8, 2020
有时间的建议先看下上篇文章 : c++11-17 模板核心知识(十三)—— 名称查找与ADL
tokenization与parsing
绝大多数语言在编译的时候都有两个阶段:
tokenization阶段会读取源码并生成一系列token. 例如:
int *p = 0;
,tokenizer会生成关键字int、运算符*、标识符p、运算符=、整数0、运算符;接下来,parser会递归的减少标记,寻找已知的模式。例如:token 0是一个合法的表达式,*p组合也是一个合法的声明,它和后面的=0组合也是一个合法初始化声明。最后,int是一个已知的类型,后面跟着初始化声明 : *p=0,所以,我们得到了一个初始化p的声明
解析模板之类型的依赖名称 Dependent Names of Templates
关于模板解析有六个大方面:
这篇文章先讲下代码中比较常见的第三点 : 依赖型模板名称(Dependent Names of Templates)
这里有一个很重要的概念 : 在c++11-17 模板核心知识(十三)—— 名称查找与ADL中介绍过的Dependent Name:依赖于模板参数的名称,也就是访问运算符左面的表达式类型依赖于模板参数。例如:std::vector::iterator是一个 Dependent Name,但假如T是一个已知类型的别名(using T = int),那就不是Dependent Name。
通常而言, 编译器会把模板名称后面的<当做模板参数列表的开始,否则,<就是比较运算符。但是,当引用的模板名称是Dependent Name时,编译器不会假定它是一个模板名称,除非显示的使用template关键字来指明,模板代码中常见的
->template
、.template
、::template
就应用于这种场景中。下面看几个例子。
Example One
这里,参数bs依赖于模板参数N。所以,我们必须通过template关键字让编译器知道bs是一个模板名称,否则按照上面的规则,
<
会被当做比较符——小于号。Example Two
The template keyword as qualifier (C++ only)中的例子:
这里,参数p依赖模板参数T。注意
typename T::template S<40> s;
的使用。Example Three
参数p依赖模板参数T。编译器不会去判断
p.Deep
是不是模板。如果不指定template,那么p.Deep<N>::f()
就会被解析成((p.Deep)<N)>f();
,<
被当做比较符。基于上面的例子,我们也可以知道,
->template
、.template
、::template
只存在于模板中,并且是在Dependent Name的场景下使用(依赖于模板参数)。(完)
朋友们可以关注下我的公众号,获得最及时的更新:
The text was updated successfully, but these errors were encountered: