如何将固定尺寸的枚举Val设置为最大值的值?

发布于 2025-01-24 19:12:29 字数 636 浏览 1 评论 0原文

这可能很简单,但我没有正确。我有一个“ bitmask”枚举,该枚举具有一个值所有,该表明所有位均已设置。但是,我无法使用〜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;
}

This is probably simple but I'm not getting it right. I have a "bitmask" enum which has a value all that indicates that all bits are set. However, I can't get it to flip all bits using ~0. The following error appears:

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

Which is strange because it should actually fit into uint8_t no? Here is my code (godbolt):

#include <iostream>

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

    mask = all;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

初熏 2025-01-31 19:12:29

您可以借助一些元编程技巧

#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;

demo

You can get the maximum value with the help of some meta-programming tricks

#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;

Demo

心如荒岛 2025-01-31 19:12:29

默认情况下,0x0是类型int。因此,如果您尝试翻转所有位,您将获得-1无法分配给枚举的类型。

即使您使用后缀作为字面值,例如u。表明字面价值是无符号类型的。如〜0x0u中。您将获得unsigned int类型的最大值。超过您使用的8位整数类型的范围。因此,这也行不通。

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

static_cast<uint_fast8_t>( ~0x0 )

但是,如果您稍后决定更改枚举的类型,则使用硬编码的类型和值有时会陷入困境。因此,如果您有C ++ 14。您可以使用std :: undlying_type type-tait,并制作一个通用实用程序:

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();

天空是极限。

By default, 0x0 is of type int. So if you try to flip all the bits you'll get -1 which can't be assigned to the type your enumeration was defined to.

Even if you use a suffix for that literal value, like u for example. To indicate that the literal value is of unsigned type. As in ~0x0u. You'd get the maximum of the unsigned int type. Which exceeds the range of the 8-bit integer type you're using. So this doesn't work either.

So you need to tell the language that you want the literal value to be of the type you need first. That can be achieved with a static_cast as demonstrated in other answers:

static_cast<uint_fast8_t>( ~0x0 )

But using hardcoded types and values can get in the way sometimes if you decide to change the type of the enum later. So if you have c++14 available. You can use the std::underlying_type type-trait and make a generic utility like:

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);

And then used like:

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

Now you don't have to care about the underlying type of the enumeration.

You can even use std::numeric_limits if you want the right values instead of relying on flipping bits:

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

Sky is the limit.

哀由 2025-01-31 19:12:29

您需要将Expression 〜0x0转换为具有类型int的类型的uint_fast8_t

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

last键入int?因为整数字面0x0具有类型int,并且操作员〜不会更改表达式的类型。

从C ++标准

2整数字面的类型是相应的第一个
表5中的列表可以表示其值。

类型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,

You need to convert the expression ~0x0 having the type int and a negative value to the type uint_fast8_t like for example

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

Why does the expression have the type int? Because the integer literal 0x0 has the type int and the operator ~ does not change the type of the expression.

From the C++ Standard

2 The type of an integer literal is the first of the corresponding
list in Table 5 in which its value can be represented.

And an object of the type int can represent the literal 0x0.

Here is a demonstration program.

#include <iostream>
#include <iomanip>
#include <type_traits>

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

The program output is

true

Another way is just to write

all = 0xff,
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文