使用模板参数缩小转换(MSVC14)

时间:2015-04-08 14:18:22

标签: 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) >> 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;
}

生成以下内容(使用Constant<0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF>()):

note: see reference to function template instantiation '__m128 Constant<2147483647,2147483647,2147483647,2147483647>(void)' being compiled
warning C4838: conversion from 'unsigned int' to 'char' requires a narrowing conversion

__m128i联合在emmintrin.h内定义,作为具有多种不同类型的数组的并集,表示MMX寄存器。要列出初始化结构,必须使用union中声明的第一个类型,在本例中为__int8。根据MSVC 2013文档(https://msdn.microsoft.com/en-us/library/29dh1w7z.aspx),__int8映射到char,我假设MSVC 2015也是如此。因此,警告似乎是有效的,因为即使模板参数是非类型的,转换后并非所有字段都适合char类型。

我的问题是为什么MSVC 2013没有对此发出警告(因为它似乎是核心的c ++ 11问题)?还有一个很好的&#39;解决警告的方法?

2 个答案:

答案 0 :(得分:2)

将shift-mask-cast因子排除:

template<unsigned n, unsigned value>
/*constexpr*/ int8_t get_byte() {
  return static_cast<int8_t>(0xFF & (value >> (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;
}

请注意get_byte返回带符号的8位整数。

注意上述对称性是如何显而易见的。

答案 1 :(得分:0)

@Chuck Walbourn - &#34;请注意,C4838是VS 2015的新功能,这就是为什么它不会出现在VS 2013中。&#34;