如何将固定大小的枚举值设置为其最大可能值?
How to set enum val of fixed size to its max possible value?
这可能很简单,但我没有做对。我有一个“位掩码”枚举,它的值 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;
}
您需要将具有类型 int
和负值的表达式 ~0x0
转换为类型 uint_fast8_t
,例如
all = static_cast<uint_fast8_t>( ~0x0 ),
为什么表达式的类型是 int
?因为整数文字 0x0
具有类型 int
并且运算符 ~ 不会更改表达式的类型。
来自 C++ 标准
2 The type of an integer literal is the first of the corresponding
list in Table 5 in which its value can be represented.
并且 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,
你可以借助一些meta-programming技巧获得最大值
#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;
默认情况下,0x0
的类型为 int
。因此,如果您尝试翻转所有位,您将得到 -1
无法分配给您的枚举定义的类型。
即使您为该文字值使用后缀,例如 u
。表示字面值是无符号类型。如 ~0x0u
。您将获得 unsigned int
类型的最大值。这超出了您正在使用的 8 位整数类型的范围。所以这也不管用。
所以你需要先告诉语言你希望文字值是你需要的类型。这可以通过 static_cast
实现,如其他答案所示:
static_cast<uint_fast8_t>( ~0x0 )
但是,如果您决定稍后更改枚举的类型,使用硬编码类型和值有时会妨碍您。所以如果你有可用的 c++14。您可以使用 std::underlying_type
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();
天空无极限。
这可能很简单,但我没有做对。我有一个“位掩码”枚举,它的值 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;
}
您需要将具有类型 int
和负值的表达式 ~0x0
转换为类型 uint_fast8_t
,例如
all = static_cast<uint_fast8_t>( ~0x0 ),
为什么表达式的类型是 int
?因为整数文字 0x0
具有类型 int
并且运算符 ~ 不会更改表达式的类型。
来自 C++ 标准
2 The type of an integer literal is the first of the corresponding list in Table 5 in which its value can be represented.
并且 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,
你可以借助一些meta-programming技巧获得最大值
#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;
默认情况下,0x0
的类型为 int
。因此,如果您尝试翻转所有位,您将得到 -1
无法分配给您的枚举定义的类型。
即使您为该文字值使用后缀,例如 u
。表示字面值是无符号类型。如 ~0x0u
。您将获得 unsigned int
类型的最大值。这超出了您正在使用的 8 位整数类型的范围。所以这也不管用。
所以你需要先告诉语言你希望文字值是你需要的类型。这可以通过 static_cast
实现,如其他答案所示:
static_cast<uint_fast8_t>( ~0x0 )
但是,如果您决定稍后更改枚举的类型,使用硬编码类型和值有时会妨碍您。所以如果你有可用的 c++14。您可以使用 std::underlying_type
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();
天空无极限。