使用模板参数缩小转换 (MSVC14)
Narrowing conversion with template parameter (MSVC14)
升级到 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 寄存器。要列表初始化结构,您必须使用联合中声明的第一个类型,在本例中为 __int8
。根据 MSVC 2013 文档 (https://msdn.microsoft.com/en-us/library/29dh1w7z.aspx),__int8
映射到 char
,我假设 MSVC 2015 也是如此。所以,警告似乎是有效的,因为即使模板参数是非类型的,转换后并非所有字段都适合 char
类型。
我的问题是为什么 MSVC 2013 没有对此发出警告(因为它看起来像是一个核心 c++11 问题)?另外,是否有 'nice' 解决警告的方法?
分解出 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
returns 一个带符号的 8 位整数。
请注意上面的对称性是多么明显。
@Chuck Walbourn - "Note that C4838 is new for VS 2015 which is why it doesn't come up in VS 2013."
升级到 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 寄存器。要列表初始化结构,您必须使用联合中声明的第一个类型,在本例中为 __int8
。根据 MSVC 2013 文档 (https://msdn.microsoft.com/en-us/library/29dh1w7z.aspx),__int8
映射到 char
,我假设 MSVC 2015 也是如此。所以,警告似乎是有效的,因为即使模板参数是非类型的,转换后并非所有字段都适合 char
类型。
我的问题是为什么 MSVC 2013 没有对此发出警告(因为它看起来像是一个核心 c++11 问题)?另外,是否有 'nice' 解决警告的方法?
分解出 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
returns 一个带符号的 8 位整数。
请注意上面的对称性是多么明显。
@Chuck Walbourn - "Note that C4838 is new for VS 2015 which is why it doesn't come up in VS 2013."