C++ C++;11:";缩小{}”内的转换;带模数

C++ C++;11:";缩小{}”内的转换;带模数,c++,c++11,narrowing,C++,C++11,Narrowing,我尝试在启用了gcc和C++11的情况下编译以下代码: unsigned int id = 100; unsigned char array[] = { id % 3, id % 5 }; 我收到以下警告: 正在缩小“{}[-Wnarrowing]内“(id%3u)”从“unsigned int”到“unsigned char”的转换范围 有没有办法帮助编译器找出id%3的结果是否适合无符号字符?您可以使用: unsigned char array[] = { static_cast

我尝试在启用了
gcc
C++11
的情况下编译以下代码:

unsigned int id = 100;
unsigned char array[] = { id % 3, id % 5 };
我收到以下警告:

正在缩小“{}[-Wnarrowing]内“(id%3u)”从“unsigned int”到“unsigned char”的转换范围

有没有办法帮助编译器找出id%3的结果是否适合无符号字符?

您可以使用:

unsigned char array[] = {
    static_cast<unsigned char>(id % 3),
    static_cast<unsigned char>(id % 5)
};
无符号字符数组[]={
静态强制转换(id%3),
静态\u转换(id%5)
};

由于
id
是一个
unsigned int
,因此
id%3
的类型也将是一个
unsigned int

编译器会提醒您,
无符号字符
(按标准为8位)可能太小,无法接收
无符号整数
(按标准至少为16位)


当然,在这个特殊情况下,你更清楚。使用
static\u cast(id%…)
告诉编译器缩小转换是安全的。

在这种特定情况下,生成
id
const或将修复问题:

constexpr unsigned int id = 100;
因为有一个例外,在这种情况下,您有一个常量表达式,其转换后的结果将适合目标类型

在更一般的情况下,还可以使用将结果强制转换为无符号字符:

{ static_cast<unsigned char>( id % 3), static_cast<unsigned char>( id % 5) }
  ^^^^^^^^^^^                          ^^^^^^^^^^^
{static_cast(id%3),static_cast(id%5)}
^^^^^^^^^^^                          ^^^^^^^^^^^
我们可以在
8.5.4
列表初始化一节中找到常量表达式和窄化转换的例外情况,其中说明:

缩小转换是一种隐式转换

并包括以下项目(强调我的):

  • 从整数类型或非作用域枚举类型到不能表示原始类型的所有值的整数类型,除了 其中,源是一个常量表达式,其值在积分之后 促销活动将适合目标类型

注意,从原来的C++ 11标准草案中的措辞变成了我引用的上述内容。

< P>这是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);
}
模板结构{using type=T;};
模板
结构最小值>{using type=U;};
templateusing minimable\u t=typename minimate::type;
constexpr结构mod_t{}mod;
templatestruct-half_-mod{LHS-LHS;};
模板
constexpr half_mod操作符%(LHS&&LHS,mod_t){return{std::forward(LHS)};}
模板
constexpr最小运算符%(半模左、右、右){
返回标准::移动(左。左)%标准::向前(右);
}
mod b的结果应该是两种类型中最小的,因为它不能更大。可能一些工作应该做的签名/未签名,但我会下注,并采取第一个


因此,
id%mod%3
最终成为
char

?您不能将结果存储在一个int数组中吗?你会用它做什么。我想有一个小错误:
operator%(LHS&&LHS,mod)
需要是
operator%(LHS&&LHS,mod)
。除此之外:这只适用于我强制转换为char:
id%mod%(char)3
,否则编译器也会将3解释为
int
。有什么办法吗?@m.s.bah,我认为常数是
char
而不是
int
。虽然很可怕,
'\3'
是字符常量
3
:如果
id
确实是一个常量,那么您最好的选择可能是
constepr