C++11 使用模板参数(MSVC14)缩小转换范围
升级到MSVC 2015后(从MSVC 2013开始),我开始收到以下代码的警告:C++11 使用模板参数(MSVC14)缩小转换范围,c++11,visual-c++,visual-studio-2015,narrowing,C++11,Visual C++,Visual Studio 2015,Narrowing,升级到MSVC 2015后(从MSVC 2013开始),我开始收到以下代码的警告: template< unsigned int i0, unsigned int i1, unsigned int i2, unsigned int i3 > static __m128 Constant( ) { static __m128i v = { ((i0&0x000000FF) >> 0 ), ((i0&0x0000FF00) >&g
template< unsigned int i0, unsigned int i1, unsigned int i2, unsigned int i3 >
static __m128 Constant( )
{
static __m128i v = {
((i0&0x000000FF) >> 0 ), ((i0&0x0000FF00) >> 8), ((i0&0x00FF0000) >> 16), ((i0&0xFF000000) >> 24),
((i1&0x000000FF) >> 0 ), ((i1&0x0000FF00) >> 8), ((i1&0x00FF0000) >> 16), ((i1&0xFF000000) >> 24),
((i2&0x000000FF) >> 0 ), ((i2&0x0000FF00) >> 8), ((i2&0x00FF0000) >> 16), ((i2&0xFF000000) >> 24),
((i3&0x000000FF) >> 0 ), ((i3&0x0000FF00) >> 8), ((i3&0x00FF0000) >> 16), ((i3&0xFF000000) >> 24) };
return *(__m128*)&v;
}
template
静态uu m128常数()
{
静态u_m128iv={
((i0&0x000000FF)>>0),((i0&0x0000FF00)>>8),((i0&0x00FF0000)>>16),((i0&0xFF000000)>>24),
((i1&0x000000FF)>>0),((i1&0x00000FF00)>>8),((i1&0x00FF0000)>>16),((i1&0xFF000000)>>24),
((i2&0x000000FF)>>0),((i2&0x00000FF00)>>8),((i2&0x00FF0000)>>16),((i2&0xFF000000)>>24),
((i3&0x000000FF)>>0),((i3&0x00000FF00)>>8),((i3&0x00FF0000)>>16),((i3&0xFF000000)>>24)};
return*(uu m128*)&v;
}
生成以下内容(使用常量()
):
注意:请参阅正在编译的函数模板实例化“\uuum128常量(void)”的参考
警告C4838:从“unsigned int”到“char”的转换需要缩小转换范围
\uuum128i
并集在emmintrin.h
中定义为具有几种不同类型的数组的并集,它们表示MMX寄存器。要列表初始化结构,必须使用union中声明的第一个类型,在本例中为\uu int8
。根据MSVC 2013文档(),\uuuu int8
映射到char
,我认为MSVC 2015也是如此。因此,该警告似乎是有效的,因为即使模板参数是非类型的,也不是所有字段在转换后都适合char
type
我的问题是,为什么MSVC 2013没有对此发出警告(因为这似乎是c++11的核心问题)?此外,是否有一种“好”的方法来解决警告?将换档遮罩投射因素考虑在内:
template<unsigned n, unsigned value>
/*constexpr*/ int8_t get_byte() {
return static_cast<int8_t>(0xFF & (value >> (n*8)));
}
模板
/*constexpr*/int8获取字节(){
返回静态_cast(0xFF&(值>>(n*8));
}
然后使用它:
template<unsigned i0, unsigned i1, unsigned i2, unsigned i3>
static __m128 Constant( )
{
static __m128i v = {
get_byte<0,i0>(), get_byte<1,i0>(), get_byte<2,i0>(), get_byte<3,i0>(),
get_byte<0,i1>(), get_byte<1,i1>(), get_byte<2,i1>(), get_byte<3,i1>(),
get_byte<0,i2>(), get_byte<1,i2>(), get_byte<2,i2>(), get_byte<3,i2>(),
get_byte<0,i3>(), get_byte<1,i3>(), get_byte<2,i3>(), get_byte<3,i3>(),
};
return *(__m128*)&v;
}
模板
静态uu m128常数()
{
静态u_m128iv={
获取字节(),获取字节(),获取字节(),获取字节(),获取字节(),
获取字节(),获取字节(),获取字节(),获取字节(),获取字节(),
获取字节(),获取字节(),获取字节(),获取字节(),获取字节(),
获取字节(),获取字节(),获取字节(),获取字节(),获取字节(),
};
return*(uu m128*)&v;
}
请注意,get_byte
返回有符号8位整数
注意上面的对称性是多么明显。@Chuck Walbourn-“注意C4838对于VS 2015是新的,这就是为什么它在VS 2013中没有出现的原因。”好的,谢谢-这是一个相当好的方式来消除警告。但是答案并不能解释VS版本之间的差异。@MuertoExcobito我对VS不能满足C++11的要求一点也不感到惊讶?MSVC2013只是C++11的四分之一成熟实现。MSVC2015可能是半生不熟的。新警告是VS 2015中初始值设定项列表的C++11标准合规性的一部分。在这些情况下,它们是标准要求的。在这一点上,MSVC2015最新CTP中的C++11支持“基本上已经成熟”。有关VS版本的功能列表,请参阅。请注意,C4838是VS 2015的新功能,这就是为什么它在VS 2013中没有出现。如果您遇到了问题,尤其是ICE,请确保
template<unsigned i0, unsigned i1, unsigned i2, unsigned i3>
static __m128 Constant( )
{
static __m128i v = {
get_byte<0,i0>(), get_byte<1,i0>(), get_byte<2,i0>(), get_byte<3,i0>(),
get_byte<0,i1>(), get_byte<1,i1>(), get_byte<2,i1>(), get_byte<3,i1>(),
get_byte<0,i2>(), get_byte<1,i2>(), get_byte<2,i2>(), get_byte<3,i2>(),
get_byte<0,i3>(), get_byte<1,i3>(), get_byte<2,i3>(), get_byte<3,i3>(),
};
return *(__m128*)&v;
}