[英]C++11: “narrowing conversion inside { }” with modulus
我尝试使用gcc
和C++11
编译以下代码:
unsigned int id = 100;
unsigned char array[] = { id % 3, id % 5 };
我收到这些警告:
缩小'(id%3u)'从'unsigned int'到{}内的'unsigned char'的转换[-Wnarrowing]
有没有办法帮助编译器发现id%3的结果符合unsigned char ?
在这个特定的情况下,使用id
const或constexpr将解决问题:
constexpr unsigned int id = 100;
因为对于具有常量表达式的情况存在例外,其转换后的结果将适合目标类型。
在更一般的情况下,您也可以使用static_cast将结果转换为unsigned char:
{ static_cast<unsigned char>( id % 3), static_cast<unsigned char>( id % 5) }
^^^^^^^^^^^ ^^^^^^^^^^^
我们可以在草案C ++标准第8.5.4
节列表初始化中找到常量表达式和缩小转换的异常,它表示:
缩小转换是隐式转换
并包括以下子弹( 强调我的 ):
- 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型, 除非源是一个常量表达式,其整数提升后的值将适合目标类型 。
这是C ++的一个怪癖,几乎所有的数学运算都将它们的参数转换为int
。
以下是非加宽%mod%
运算符的草图:
template<class T, class U,class=void> struct smallest{using type=T;};
template<class T, class U>
struct smallest<T,U,std::enable_if_t<(sizeof(T)>sizeof(U))>>{using type=U;};
template<class T,class U>using smallest_t=typename smallest<T,U>::type;
constexpr struct mod_t {} mod;
template<class LHS>struct half_mod { LHS lhs; };
template<class LHS>
constexpr half_mod<std::decay_t<LHS>> operator%( LHS&& lhs, mod_t ) { return {std::forward<LHS>(lhs)}; }
template<class LHS, class RHS>
constexpr smallest_t<LHS, std::decay_t<RHS>> operator%( half_mod<LHS>&& lhs, RHS&& rhs ) {
return std::move(lhs.lhs) % std::forward<RHS>(rhs);
}
mod b的结果应该是两种类型中最小的,因为它不能更大。 可能应该为签名/未签名做一些工作,但我会先试探并采取第一个。
所以id %mod% 3
最终成为char
。
你可以使用:
unsigned char array[] = {
static_cast<unsigned char>(id % 3),
static_cast<unsigned char>(id % 5)
};
由于id
是unsigned int
,因此id % 3
的类型也将是unsigned int
。
您的编译器有助于警告您unsigned char
(标准为8位) 可能太小而无法接收unsigned int
(标准unsigned int
至少为16位)。
当然,在这个特定情况下你会更清楚。 使用static_cast<unsigned char>(id % ...)
告诉编译器缩小转换是安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.