我正在使用C++Primer第5版学习非类型模板参数,并了解到:
非类型参数可以是整型,也可以是指向对象或函数类型的指针或(左值(引用。绑定到非类型积分参数的参数必须是常量表达式。
现在,为了进一步澄清我的概念并确认我正确理解了这个主题,我编写了以下程序,该程序使用msvc编译,但不使用clang。演示
#include <iostream>
template<char N> class S
{
public:
S()
{
std::cout << "char template" << std::endl;
}
};
int main()
{
S<128> s1; //MSVC compiles this but gcc and clang rejects
}
所以我的问题是哪一个编译器就在这里(如果有的话(。我试着在书中查找这个,但根据c++标准,我不知道这个程序是否有效。MSVC编译这个,而gcc和clang说:
error: non-type template argument evaluates to 128, which cannot be narrowed to type 'char'
程序是格式错误,msvc接受代码是错误的,因为从整数文本128
到char
的转换是缩小转换,这在本文中是不允许的,如下所述。基本上,这失败的原因与char ch{128};
失败的原因相同,即两者都涉及带窄化转换的积分转换。
来自非类型#2的临时参数:
非类型模板参数的模板参数应为模板参数类型的转换常量表达式。
现在从转换的常量表达式:
4(类型T的转换常量表达式是一个隐式转换为类型T的表达式,其中转换表达式是常量表达式,隐式转换序列仅包含
4.7( 除缩小转换之外的积分转换
但请注意,从int128
到char
的积分转换是一种窄化转换,从窄化转换可以看出:
7(缩小转换是一种隐式转换
7.4(从整数类型或无范围枚举类型转换为不能表示原始类型的所有值的整数类型,除非源是一个常量表达式,其值在整数提升后将适合目标类型。
(强调矿(
因此,在char
有符号的情况下,从int128
到char
的积分转换涉及缩小转换,因此是不允许的(不是转换后的常量表达式(,因此msvc在接受代码时是错误的。
以下是msvc错误报告:
MSVC在非类型模板参数中编译无效的缩小转换