为何C++模板类代码在GCC 11.1下报expected primary-expression错误
问题原因分析
根本原因
这是C模板两阶段查找规则中,依赖类型的成员模板调用必须显式标记template关键字的典型场景。
C标准规定,模板在编译时会分为两个阶段处理:
- 第一阶段(模板定义阶段):仅检查语法错误,查找所有不依赖模板参数的非依赖名,依赖于模板参数的名字会推迟到实例化阶段处理。
- 第二阶段(模板实例化阶段):传入具体模板参数后,再查找所有依赖名。
对于依赖类型(类型由模板参数决定)的对象,如果你要调用它的成员模板,必须在成员模板名前加上template关键字,否则编译器会把成员名后的<解析为「小于运算符」,而不是模板参数列表的起始,就会出现你遇到的语法报错。
两种写法的差异
第一种报错写法
return container().address<E>(m_pos);
container()的返回类型是const ring<T, Allocator>&,这个类型依赖于外层ring类的模板参数T和Allocator,属于依赖类型。编译器在第一阶段处理时,不知道address是成员模板,就把<解析为小于号,后面的E和>就不符合语法规则,直接报错。
如果不想拆分变量,可以显式加template关键字修复:
return container().template address<E>(m_pos);
第二种正常编译写法
const ring& r = container(); return r.address<E>(m_pos);
在ring类的嵌套类ring_iterator的作用域内,ring指代的是当前已经实例化的ring<T, Allocator>类,属于非依赖类型。编译器在第一阶段就能直接在ring的定义中找到address是成员模板,不需要额外加template关键字就能正确解析<为模板参数列表的开头,因此编译通过。
内容的提问来源于stack exchange,提问作者Dmitriano
相关产品推荐
相关产品推荐

