FE 0.13.1
Header-only C++ frontend library
Loading...
Searching...
No Matches
enum.h
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4
5#include <type_traits>
6
7namespace fe {
8
9/// @name Bit operations for enum classs
10/// Provides all kind of bit and comparison operators for an `enum class` @p E.
11/// Use like this:
12/// ```
13/// enum class MyEnum : unsigned {
14/// A = 1 << 0,
15/// B = 1 << 1,
16/// C = 1 << 2,
17/// };
18///
19/// template<> struct fe::is_bit_enum<MyEnum> : std::true_type {};
20/// ```
21template<typename T>
22struct is_bit_enum : std::false_type {};
23
24template<typename E>
25concept BitEnum = std::is_enum_v<E> && is_bit_enum<E>::value;
26
27template<fe::BitEnum E>
28constexpr auto to_underlying(E e) noexcept {
29 return static_cast<std::underlying_type_t<E>>(e);
30}
31
32} // namespace fe
33
34// clang-format off
35template<fe::BitEnum E> constexpr E operator|(E a, E b) noexcept { return static_cast<E>(fe::to_underlying(a) | fe::to_underlying(b)); }
36template<fe::BitEnum E> constexpr E operator&(E a, E b) noexcept { return static_cast<E>(fe::to_underlying(a) & fe::to_underlying(b)); }
37template<fe::BitEnum E> constexpr E operator^(E a, E b) noexcept { return static_cast<E>(fe::to_underlying(a) ^ fe::to_underlying(b)); }
38template<fe::BitEnum E> constexpr E operator~(E a) noexcept { return static_cast<E>(~fe::to_underlying(a)); }
39template<fe::BitEnum E> constexpr E& operator|=(E& a, E b) noexcept { return a = (a | b); }
40template<fe::BitEnum E> constexpr E& operator&=(E& a, E b) noexcept { return a = (a & b); }
41template<fe::BitEnum E> constexpr E& operator^=(E& a, E b) noexcept { return a = (a ^ b); }
42
43namespace fe {
44/// @note @p flag must have at least one bit set; `has_flag(value, E{})` would be vacuously `true`.
45/// `flag` is a runtime value, so this is a runtime `assert` rather than a `static_assert`
46/// (in a `constexpr` evaluation a zero @p flag turns it into a compile-time error all the same).
47template<fe::BitEnum E> constexpr bool has_flag(E value, E flag) noexcept {
48 assert(to_underlying(flag) != 0 && "flag must have at least one bit set");
49 return (value & flag) == flag;
50}
51} // namespace fe
52
53// clang-format on
constexpr E operator~(E a) noexcept
Definition enum.h:38
constexpr E operator&(E a, E b) noexcept
Definition enum.h:36
constexpr E & operator&=(E &a, E b) noexcept
Definition enum.h:40
constexpr E & operator|=(E &a, E b) noexcept
Definition enum.h:39
constexpr E operator|(E a, E b) noexcept
Definition enum.h:35
constexpr E operator^(E a, E b) noexcept
Definition enum.h:37
constexpr E & operator^=(E &a, E b) noexcept
Definition enum.h:41
Definition algo.h:17
constexpr auto to_underlying(E e) noexcept
Definition enum.h:28
constexpr bool has_flag(E value, E flag) noexcept
Definition enum.h:47