跨编译器的诊断不一致,用于缩小非类型模板参数中的转换

Posted

技术标签:

【中文标题】跨编译器的诊断不一致,用于缩小非类型模板参数中的转换【英文标题】:inconsistent diagnostics across compilers for narrowing conversions in non-type template argument 【发布时间】:2020-11-29 02:43:48 【问题描述】:
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 编译没有错误。

谁是正确的?我认为错误是正确的,但想确认一下。

【问题讨论】:

【参考方案1】:

这是不正确的,因为对于template non-type argument,

可与非类型模板形参一起使用的模板实参可以是模板形参类型的任何converted constant expression。

并且窄转换不被视为converted constant expression。

T类型的转换后的常量表达式是implicitly converted到T类型的表达式,其中转换后的表达式是常量表达式,隐式转换序列只包含:

... 非窄化整数转换 ...

【讨论】:

应该由符合标准的编译器诊断它吗? @Yashas 我不确定 MSVC,gcc 似乎已从 gcc 9.1 修复。 @Yashas 是的,符合标准的编译器应该进行诊断。 这个答案是否适用于c++11? @Yashas 是的,我检查了 C++11 标准,temp.arg.nontype#1.1,对于整数或枚举类型的非类型模板参数,转换的常量表达式([expr. const]) 的模板参数的类型; 和expr.const#3,和除窄转换以外的整数转换([conv.integral])

以上是关于跨编译器的诊断不一致,用于缩小非类型模板参数中的转换的主要内容,如果未能解决你的问题,请参考以下文章

C++11 中的非类型可变参数函数模板

是否可以将指针视为非类型模板参数中的整数类型?

C++初阶第十三篇—模板进阶(非类型模板参数+模板特化+模板的分离编译)

C++模板进阶操作 —— 非类型模板参数模板的特化以及模板的分离编译

[C/C++]详解C++中的模板

[C/C++]详解C++中的模板