不同编译器对非类型模板实参窄化转换的诊断正确性咨询
模板实参窄化转换的编译器诊断正确性确认
先来看你给出的代码示例:
template <bool> void f() { } int main () { constexpr long long int num = 5; f<num & 4>(); // bitwise & is intended return 0; }
各编译器的表现如下:
- GCC 9:抛出两个错误,分别是
error: no matching function for call to 'f<(5 & 4)>()'和error: narrowing conversion of '4' from 'long long int' to 'bool' [-Wnarrowing] - Clang:报错
error: no matching function for call to 'f' - GCC 8 及 MSVC:可以正常编译
你的判断完全正确——报错的编译器(GCC 9、Clang)的诊断才是符合C++标准要求的。
原因解析:
根据C++11及后续标准的规定,当模板非类型参数是bool类型时,传入的实参必须是一个能隐式转换为bool的常量表达式,但这里存在一个关键问题:num & 4的计算结果是long long类型的4,将这个值隐式转换为bool属于窄化转换。
窄化转换是标准明确禁止出现在常量表达式上下文(比如模板实参)中的行为——因为long long的取值范围远大于bool,即使非零值会被转为true,这个隐式转换过程也违反了标准对模板实参类型匹配的严格要求。
GCC 8和MSVC能编译通过,是因为旧版本的编译器对这个标准条款的执行不够严格,或者在模板实参场景下的窄化转换检查存在疏漏,但这并不代表它们的行为是正确的。
如果想要让代码在所有标准兼容的编译器上都能正常编译,只需要显式地将结果转换为bool即可,修改后的代码如下:
template <bool> void f() { } int main () { constexpr long long int num = 5; f<static_cast<bool>(num & 4)>(); // 显式转换避免窄化问题 return 0; }
内容的提问来源于stack exchange,提问作者Yashas
相关产品推荐
相关产品推荐

