C++11 使用模板参数(MSVC14)缩小转换范围

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

升级到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) >> 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;
}