OpenTTD Source 20250205-master-gfd85ab1e2c
enum_type.hpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#ifndef ENUM_TYPE_HPP
11#define ENUM_TYPE_HPP
12
14template <typename enum_type>
15constexpr std::underlying_type_t<enum_type> to_underlying(enum_type e) { return static_cast<std::underlying_type_t<enum_type>>(e); }
16
18template <typename enum_type>
20 static constexpr bool value = false;
21};
22
23template <typename enum_type>
24constexpr bool is_enum_incrementable_v = is_enum_incrementable<enum_type>::value;
25
27template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
28inline constexpr enum_type &operator ++(enum_type &e)
29{
30 e = static_cast<enum_type>(to_underlying(e) + 1);
31 return e;
32}
33
35template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
36inline constexpr enum_type operator ++(enum_type &e, int)
37{
38 enum_type e_org = e;
39 ++e;
40 return e_org;
41}
42
44template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
45inline constexpr enum_type &operator --(enum_type &e)
46{
47 e = static_cast<enum_type>(to_underlying(e) - 1);
48 return e;
49}
50
52template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
53inline constexpr enum_type operator --(enum_type &e, int)
54{
55 enum_type e_org = e;
56 --e;
57 return e_org;
58}
59
61#define DECLARE_INCREMENT_DECREMENT_OPERATORS(enum_type) \
62 template <> struct is_enum_incrementable<enum_type> { \
63 static const bool value = true; \
64 };
65
66
68#define DECLARE_ENUM_AS_BIT_SET(enum_type) \
69 inline constexpr enum_type operator | (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) | to_underlying(m2)); } \
70 inline constexpr enum_type operator & (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
71 inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
72 inline constexpr enum_type& operator |= (enum_type& m1, enum_type m2) { m1 = m1 | m2; return m1; } \
73 inline constexpr enum_type& operator &= (enum_type& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
74 inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
75 inline constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
76
78#define DECLARE_ENUM_AS_ADDABLE(EnumType) \
79 template <typename OtherEnumType, typename = typename std::enable_if<std::is_enum_v<OtherEnumType>, OtherEnumType>::type> \
80 constexpr OtherEnumType operator + (OtherEnumType m1, EnumType m2) { \
81 return static_cast<OtherEnumType>(to_underlying(m1) + to_underlying(m2)); \
82 }
83
90template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
91debug_inline constexpr bool HasFlag(const T x, const T y)
92{
93 return (x & y) == y;
94}
95
101template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
102debug_inline constexpr void ToggleFlag(T &x, const T y)
103{
104 if (HasFlag(x, y)) {
105 x &= ~y;
106 } else {
107 x |= y;
108 }
109}
110
117template <typename Tenum, typename Tstorage>
119public:
120 using EnumType = Tenum;
121 using BaseType = Tstorage;
122
123 constexpr EnumBitSet() : data(0) {}
124 constexpr EnumBitSet(Tenum value) : data(0) { this->Set(value); }
125 explicit constexpr EnumBitSet(Tstorage data) : data(data) {}
126
131 constexpr EnumBitSet(std::initializer_list<const Tenum> values) : data(0)
132 {
133 for (const Tenum &value : values) {
134 this->Set(value);
135 }
136 }
137
138 constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
139
145 inline constexpr EnumBitSet &Set(Tenum value)
146 {
147 this->data |= (1U << to_underlying(value));
148 return *this;
149 }
150
156 inline constexpr EnumBitSet &Reset(Tenum value)
157 {
158 this->data &= ~(1U << to_underlying(value));
159 return *this;
160 }
161
167 inline constexpr EnumBitSet &Flip(Tenum value)
168 {
169 if (this->Test(value)) {
170 return this->Reset(value);
171 } else {
172 return this->Set(value);
173 }
174 }
175
181 inline constexpr bool Test(Tenum value) const
182 {
183 return (this->data & (1U << to_underlying(value))) != 0;
184 }
185
191 inline constexpr bool All(const EnumBitSet &other) const
192 {
193 return (this->data & other.data) == other.data;
194 }
195
201 inline constexpr bool Any(const EnumBitSet &other) const
202 {
203 return (this->data & other.data) != 0;
204 }
205
206 inline constexpr EnumBitSet operator |(const EnumBitSet &other) const
207 {
208 return EnumBitSet{static_cast<Tstorage>(this->data | other.data)};
209 }
210
211 inline constexpr EnumBitSet operator &(const EnumBitSet &other) const
212 {
213 return EnumBitSet{static_cast<Tstorage>(this->data & other.data)};
214 }
215
220 inline constexpr Tstorage base() const noexcept
221 {
222 return this->data;
223 }
224
225private:
226 Tstorage data;
227};
228
229#endif /* ENUM_TYPE_HPP */
Enum-as-bit-set wrapper.
Tstorage BaseType
Storage type of this EnumBitSet, be ConvertibleThroughBase.
constexpr EnumBitSet(std::initializer_list< const Tenum > values)
Construct an EnumBitSet from a list of enum values.
constexpr bool All(const EnumBitSet &other) const
Test if all of the enum values are set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this EnumBitSet.
constexpr EnumBitSet & Set(Tenum value)
Set the enum value.
constexpr bool Any(const EnumBitSet &other) const
Test if any of the enum values are set.
Tenum EnumType
Enum type of this EnumBitSet.
Tstorage data
Bitmask of enum values.
constexpr EnumBitSet & Flip(Tenum value)
Flip the enum value.
constexpr EnumBitSet & Reset(Tenum value)
Reset the enum value to not set.
constexpr bool Test(Tenum value) const
Test if the enum value is set.
constexpr enum_type & operator--(enum_type &e)
Prefix decrement.
Definition enum_type.hpp:45
debug_inline constexpr void ToggleFlag(T &x, const T y)
Toggle a value in a bitset enum.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Definition enum_type.hpp:15
constexpr enum_type & operator++(enum_type &e)
Prefix increment.
Definition enum_type.hpp:28
debug_inline constexpr bool HasFlag(const T x, const T y)
Checks if a value in a bitset enum is set.
Definition enum_type.hpp:91
Trait to enable prefix/postfix incrementing operators.
Definition enum_type.hpp:19