如何将固定大小的enum val设置为其最大可能值?

  • 本文关键字:设置 enum val c++ enums bitmask
  • 更新时间 :
  • 英文 :


这可能很简单,但我没有得到正确的。我有一个"位掩码"enum,取值为all,表示设置所有位。然而,我不能使用~0让它翻转所有位。出现以下错误:

<source>:11:16: error: enumerator value '-1' is outside the range of underlying type 'uint_fast8_t' {aka 'unsigned char'}
11 |         all = ~0x0,
|             

这是奇怪的,因为它实际上应该适合uint8_t没有?下面是我的代码(godbolt):

#include <iostream>
int main()
{
enum mask_t : uint_fast8_t {
first = 0x1,
second = 0x2,
all = ~0x0,
} mask;
mask = all;
}

您可以借助一些元编程技巧获得最大值

#include <limits>
#include <type_traits>
#include <cstdint>
enum mask_t : uint_fast8_t {
first = 0x1,
second = 0x2,
all = std::numeric_limits<std::underlying_type_t<mask_t>>::max()
} mask;

演示

默认0x0int类型。因此,如果您尝试翻转所有位,您将得到-1,它不能分配给枚举定义的类型。

即使您为该文字值使用后缀,例如u。指示文字值为无符号类型。如~0x0u。你会得到unsigned int类型的最大值。这超出了您正在使用的8位整数类型的范围。所以这个也不行

因此,您需要告诉语言,您希望文字值首先是您需要的类型。这可以通过static_cast实现,如其他答案所示:

static_cast<uint_fast8_t>( ~0x0 )

但是,如果稍后决定更改枚举的类型,使用硬编码的类型和值有时会造成阻碍。如果你有c++14可用。您可以使用std::underlying_type类型trait并创建一个通用实用程序,如:

template < class T > constexpr std::underlying_type_t< T > enum_max_v = ~static_cast< std::underlying_type_t< T > >(0);
// If you have c++17 available with the inline keyword
// template < class T > inline constexpr std::underlying_type_t< T > enum_max_v = ~static_cast< std::underlying_type_t< T > >(0);

然后像这样使用:

enum mask_t : uint_fast8_t {
first = 0x1,
second = 0x2,
all = enum_max_v< mask_t >,
} mask;

现在您不必关心枚举的底层类型。

如果你想要正确的值,你甚至可以使用std::numeric_limits,而不是依赖于翻转位:

template < class T > constexpr std::underlying_type_t< T > enum_max_v = std::numeric_limits< std::underlying_type_t< T > >::max();

天空是极限。

您需要将类型为int且带有负值的表达式~0x0转换为类型为uint_fast8_t的表达式,例如

all = static_cast<uint_fast8_t>( ~0x0 ),

为什么表达式的类型是int?因为整型字面值0x0的类型是int,而操作符~不会改变表达式的类型。

选自c++标准

2整数字面值的类型是第一个对应的

类型为int的对象可以表示字面值0x0

这是一个示范程序。

#include <iostream>
#include <iomanip>
#include <type_traits>
int main()
{

std::cout << std::boolalpha << std::is_same_v<int, decltype( 0x0 )> << 'n';
}

程序输出为

true

另一种方法是写

all = 0xff,

最新更新