模板尖括号被解析为>运算符引发的诡异编译错误
问题原因与解决办法
解决办法
直接在调用基类的模板成员函数时添加template关键字,修正后的G()函数代码如下:
void G() { Base<i>::template F<Enum::a, Enum::b>(1); }
原因解析
这是C++中依赖名称模板解析的典型问题:
- 你的
Base<i>是一个依赖于模板参数i的类型(称为依赖基类),编译器在处理模板Derived的定义阶段(还没到实例化阶段),无法确定Base<i>::F到底是普通成员函数、成员变量还是模板成员函数。 - 按照C++标准规则,此时编译器会默认把
F当成非模板名称,于是将<符号解析成小于运算符,而非模板参数列表的开始。这就导致Base<i>::F<Enum::a, Enum::b>被错误解析:先计算Base<i>::F < Enum::a,再处理逗号表达式后的Enum::b,最终触发了operator>不匹配的错误(编译器误以为你在写类似(F < Enum::a) > Enum::b的代码)。 - 移除第二个模板参数时,
Base<i>::F<Enum::a>(1)看起来更像函数调用,编译器可能通过启发式解析"蒙对"了,但这并不是符合标准的写法。
而icc 17能正常编译是因为它实现了额外的启发式逻辑,试图自动识别这种场景,但这并不是标准要求的行为,依赖这种行为会导致代码在其他编译器(比如旧版GCC、你遇到的Intel编译器版本)上编译失败。
内容的提问来源于stack exchange,提问作者ThreeStarProgrammer57
相关产品推荐
相关产品推荐

