安全地将整数与强类型枚举进行比较
如果可能整数值可能不在枚举值范围内,如何安全地将未知类型的整数值与强类型枚举进行比较?安全地将整数与强类型枚举进行比较
最明显的方法来整数值进行比较,以枚举将投积分值,a
,以枚举类型,E
,并比较枚举值b
,就像这样:
template <typename I, typename E> bool compare(I a, E b) { return static_cast<E>(a) == b; }
然而,如果a
不在枚举值的范围内,这导致未指定的行为,每[expr.static.cast]/10:
整型或枚举类型的值可以显式转换到一个enumerati类型。如果原始值在枚举值(7.2)的范围内,则值不变。否则,结果值未指定(可能不在该范围内)。
这可以在所得到的故障可以看出(compare
如上):
enum E : uint8_t { A = 0 }; compare(256, E::A); // returns true, 256 == E::A, but E::A = 0
人们可以代替投枚举到整体式,但是这可能会导致不正确的结果,如果积分类型可以不代表所有的枚举值:
enum E : int { A = 256 }; template <typename I, typename E>
bool compare(I a, E b) { return a == static_cast<I>(b); }
compare((uint8_t)0); // returns true, 0 == E::A, but E:A = 256
回答:
枚举可以转换为其基础整型,这可以保证能够表示所有枚举的值。
template <typename I, typename E> bool compare(I a, E b) { return a == static_cast<std::underlying_type_t<E>>(b); }
仍然有可能发行与通常的算术转换如果积分类型和枚举类型signededness不同。
enum class : int32_t { A = -1 }; compare(4294967295u, E3::A); // returns true
这里,E::A
= (int32_t)-1
被转换成unsigned int
,它不能代表-1,将其转化为(最可能)4294967295
这种转换,整数的另一整体式哪些不能表示它的值,只有当一个类型是无符号且另一个类型具有负值(因此必须是签名类型)时才会发生。由于无符号值和负值不可能相等,因此我们可以告诉比较结果而无需比较确切的值。
template <typename I, typename E> bool compare(I a, E b) {
using UTE = std::underlying_type_t<E>;
return !(std::is_unsigned_v<I> && static_cast<UTE>(b) < 0) &&
!(std::is_unsigned_v<UTE> && a < 0) &&
a == static_cast<UTE>(b);
}
这将正确地赶上病例均为负值将被转换为无符号的值,则可能会匹配其他操作。由于编译器知道编译时的类型,它可以将符号检查表达式优化为a
和b
类型的适当值,即a<0
或。
以上是 安全地将整数与强类型枚举进行比较 的全部内容, 来源链接: utcz.com/qa/259793.html