OpenTTD Source 20260531-master-g0e951f3528
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 template <typename OtherEnumType, typename = typename std::enable_if<std::is_enum_v<OtherEnumType>, OtherEnumType>::type> \
173 constexpr OtherEnumType operator -(OtherEnumType m1, EnumType m2) { \
174 return static_cast<OtherEnumType>(to_underlying(m1) - to_underlying(m2)); \
175 }
176
183template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
184[[debug_inline]] inline constexpr bool HasFlag(const T x, const T y)
185{
186 return (x & y) == y;
187}
188
194template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
195[[debug_inline]] inline constexpr void ToggleFlag(T &x, const T y)
196{
197 if (HasFlag(x, y)) {
198 x &= ~y;
199 } else {
200 x |= y;
201 }
202}
203
205template <typename Tstorage, typename Tenum, Tenum Tend_value>
207 static constexpr Tstorage value = std::numeric_limits<Tstorage>::max() >> (std::numeric_limits<Tstorage>::digits - to_underlying(Tend_value));
208};
209
218template <typename Tenum, typename Tstorage, Tenum Tend_value = Tenum{std::numeric_limits<Tstorage>::digits}>
219class EnumBitSet : public BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage, EnumBitSetMask<Tstorage, Tenum, Tend_value>::value> {
220 using BaseClass = BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage, EnumBitSetMask<Tstorage, Tenum, Tend_value>::value>;
221public:
222 using EnumType = BaseClass::ValueType;
223
224 constexpr EnumBitSet() : BaseClass() {}
225 constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
226 explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data) {}
227
232 constexpr EnumBitSet(std::initializer_list<const Tenum> values) : BaseClass()
233 {
234 for (const Tenum &value : values) {
235 this->Set(value);
236 }
237 }
238
239 constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
240
241 static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); }
242};
243
250template <typename Container, typename Index>
251class EnumClassIndexContainer : public Container {
252public:
253 Container::reference at(size_t pos) = delete;
254 Container::reference at(const Index &pos) { return this->Container::at(to_underlying(pos)); }
255
256 Container::const_reference at(size_t pos) const = delete;
257 Container::const_reference at(const Index &pos) const { return this->Container::at(to_underlying(pos)); }
258
259 Container::reference operator[](size_t pos) = delete;
260 Container::reference operator[](const Index &pos) { return this->Container::operator[](to_underlying(pos)); }
261
262 Container::const_reference operator[](size_t pos) const = delete;
263 Container::const_reference operator[](const Index &pos) const { return this->Container::operator[](to_underlying(pos)); }
264};
265
272template <typename T, typename Index, Index N>
274
275#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.
#define T
Climate temperate.
Definition engines.h:91
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.
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
constexpr enum_type operator-(enum_type e, int offset)
Subtract integer.
constexpr enum_type operator+(enum_type e, int offset)
Add integer.
#define debug_inline
When making a (pure) debug build, the compiler will by default disable inlining of functions.
Definition stdafx.h:222
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