OpenTTD Source 20260218-master-g2123fca5ea
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef ENUM_TYPE_HPP
11#define ENUM_TYPE_HPP
12
13#include "base_bitset_type.hpp"
14
20template <typename enum_type>
21constexpr std::underlying_type_t<enum_type> to_underlying(enum_type e) { return static_cast<std::underlying_type_t<enum_type>>(e); }
22
24template <class T> constexpr bool is_scoped_enum_v = std::conjunction_v<std::is_enum<T>, std::negation<std::is_convertible<T, int>>>;
25
27template <typename enum_type>
29 static constexpr bool value = false;
30};
31
32template <typename enum_type>
33constexpr bool is_enum_incrementable_v = is_enum_incrementable<enum_type>::value;
34
40template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
41inline constexpr enum_type &operator ++(enum_type &e)
42{
43 e = static_cast<enum_type>(to_underlying(e) + 1);
44 return e;
45}
46
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
65template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
66inline constexpr enum_type &operator --(enum_type &e)
67{
68 e = static_cast<enum_type>(to_underlying(e) - 1);
69 return e;
70}
71
77template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
78inline constexpr enum_type operator --(enum_type &e, int)
79{
80 enum_type e_org = e;
81 --e;
82 return e_org;
83}
84
86#define DECLARE_INCREMENT_DECREMENT_OPERATORS(enum_type) \
87 template <> struct is_enum_incrementable<enum_type> { \
88 static const bool value = true; \
89 };
90
92template <typename enum_type>
94 static constexpr bool value = false;
95};
96
97template <typename enum_type>
98constexpr bool is_enum_sequential_v = is_enum_sequential<enum_type>::value;
99
106template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
107inline constexpr enum_type operator+(enum_type e, int offset)
108{
109 return static_cast<enum_type>(to_underlying(e) + offset);
110}
111
112template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
113inline constexpr enum_type &operator+=(enum_type &e, int offset)
114{
115 e = e + offset;
116 return e;
117}
118
125template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
126inline constexpr enum_type operator-(enum_type e, int offset)
127{
128 return static_cast<enum_type>(to_underlying(e) - offset);
129}
130
131template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
132inline constexpr enum_type &operator-=(enum_type &e, int offset)
133{
134 e = e - offset;
135 return e;
136}
137
144template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
145inline constexpr auto operator-(enum_type a, enum_type b)
146{
147 return to_underlying(a) - to_underlying(b);
148}
149
151#define DECLARE_ENUM_AS_SEQUENTIAL(enum_type) \
152 template <> struct is_enum_sequential<enum_type> { \
153 static const bool value = true; \
154 };
155
157#define DECLARE_ENUM_AS_BIT_SET(enum_type) \
158 inline constexpr enum_type operator | (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) | to_underlying(m2)); } \
159 inline constexpr enum_type operator & (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
160 inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
161 inline constexpr enum_type& operator |= (enum_type& m1, enum_type m2) { m1 = m1 | m2; return m1; } \
162 inline constexpr enum_type& operator &= (enum_type& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
163 inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
164 inline constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
165
167#define DECLARE_ENUM_AS_ADDABLE(EnumType) \
168 template <typename OtherEnumType, typename = typename std::enable_if<std::is_enum_v<OtherEnumType>, OtherEnumType>::type> \
169 constexpr OtherEnumType operator + (OtherEnumType m1, EnumType m2) { \
170 return static_cast<OtherEnumType>(to_underlying(m1) + to_underlying(m2)); \
171 }
172
179template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
180[[debug_inline]] inline constexpr bool HasFlag(const T x, const T y)
181{
182 return (x & y) == y;
183}
184
190template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
191[[debug_inline]] inline constexpr void ToggleFlag(T &x, const T y)
192{
193 if (HasFlag(x, y)) {
194 x &= ~y;
195 } else {
196 x |= y;
197 }
198}
199
201template <typename Tstorage, typename Tenum, Tenum Tend_value>
203 static constexpr Tstorage value = std::numeric_limits<Tstorage>::max() >> (std::numeric_limits<Tstorage>::digits - to_underlying(Tend_value));
204};
205
214template <typename Tenum, typename Tstorage, Tenum Tend_value = Tenum{std::numeric_limits<Tstorage>::digits}>
215class EnumBitSet : public BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage, EnumBitSetMask<Tstorage, Tenum, Tend_value>::value> {
216 using BaseClass = BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage, EnumBitSetMask<Tstorage, Tenum, Tend_value>::value>;
217public:
218 using EnumType = BaseClass::ValueType;
219
220 constexpr EnumBitSet() : BaseClass() {}
221 constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
222 explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data) {}
223
228 constexpr EnumBitSet(std::initializer_list<const Tenum> values) : BaseClass()
229 {
230 for (const Tenum &value : values) {
231 this->Set(value);
232 }
233 }
234
235 constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
236
237 static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); }
238};
239
246template <typename Container, typename Index>
247class EnumClassIndexContainer : public Container {
248public:
249 Container::reference at(size_t pos) { return this->Container::at(pos); }
250 Container::reference at(const Index &pos) { return this->Container::at(to_underlying(pos)); }
251
252 Container::const_reference at(size_t pos) const { return this->Container::at(pos); }
253 Container::const_reference at(const Index &pos) const { return this->Container::at(to_underlying(pos)); }
254
255 Container::reference operator[](size_t pos) { return this->Container::operator[](pos); }
256 Container::reference operator[](const Index &pos) { return this->Container::operator[](to_underlying(pos)); }
257
258 Container::const_reference operator[](size_t pos) const { return this->Container::operator[](pos); }
259 Container::const_reference operator[](const Index &pos) const { return this->Container::operator[](to_underlying(pos)); }
260};
261
262#endif /* ENUM_TYPE_HPP */
Base for bitset types that accept strong types, ones that need some casting like StrongType and enum ...
Tstorage data
Bitmask of values.
constexpr BaseBitSet()
Create an empty bitset.
constexpr Timpl & Set()
Set all bits.
Enum-as-bit-set wrapper.
constexpr EnumBitSet(std::initializer_list< const Tenum > values)
Construct an EnumBitSet from a list of enum values.
A sort-of mixin that implements 'at(pos)' and 'operator[](pos)' only for a specific enum class.
constexpr enum_type & operator--(enum_type &e)
Prefix decrement.
Definition enum_type.hpp:66
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:21
constexpr enum_type & operator++(enum_type &e)
Prefix increment.
Definition enum_type.hpp:41
constexpr bool is_scoped_enum_v
Implementation of std::is_scoped_enum_v (from C++23).
Definition enum_type.hpp:24
constexpr bool HasFlag(const T x, const T y)
Checks if a value in a bitset enum is set.
constexpr enum_type operator-(enum_type e, int offset)
Subtract integer.
constexpr enum_type operator+(enum_type e, int offset)
Add integer.
Helper template structure to get the mask for an EnumBitSet from the end enum value.
Trait to enable prefix/postfix incrementing operators.
Definition enum_type.hpp:28
Trait to enable prefix/postfix incrementing operators.
Definition enum_type.hpp:93