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