OpenTTD Source 20260129-master-g2bb01bd0e4
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
10#ifndef ENUM_TYPE_HPP
11#define ENUM_TYPE_HPP
12
13#include "base_bitset_type.hpp"
14
16template <typename enum_type>
17constexpr std::underlying_type_t<enum_type> to_underlying(enum_type e) { return static_cast<std::underlying_type_t<enum_type>>(e); }
18
20template <class T> constexpr bool is_scoped_enum_v = std::conjunction_v<std::is_enum<T>, std::negation<std::is_convertible<T, int>>>;
21
23template <typename enum_type>
25 static constexpr bool value = false;
26};
27
28template <typename enum_type>
29constexpr bool is_enum_incrementable_v = is_enum_incrementable<enum_type>::value;
30
32template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
33inline constexpr enum_type &operator ++(enum_type &e)
34{
35 e = static_cast<enum_type>(to_underlying(e) + 1);
36 return e;
37}
38
40template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
41inline constexpr enum_type operator ++(enum_type &e, int)
42{
43 enum_type e_org = e;
44 ++e;
45 return e_org;
46}
47
49template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
50inline constexpr enum_type &operator --(enum_type &e)
51{
52 e = static_cast<enum_type>(to_underlying(e) - 1);
53 return e;
54}
55
57template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
58inline constexpr enum_type operator --(enum_type &e, int)
59{
60 enum_type e_org = e;
61 --e;
62 return e_org;
63}
64
66#define DECLARE_INCREMENT_DECREMENT_OPERATORS(enum_type) \
67 template <> struct is_enum_incrementable<enum_type> { \
68 static const bool value = true; \
69 };
70
72template <typename enum_type>
74 static constexpr bool value = false;
75};
76
77template <typename enum_type>
78constexpr bool is_enum_sequential_v = is_enum_sequential<enum_type>::value;
79
81template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
82inline constexpr enum_type operator+(enum_type e, int offset)
83{
84 return static_cast<enum_type>(to_underlying(e) + offset);
85}
86
87template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
88inline constexpr enum_type &operator+=(enum_type &e, int offset)
89{
90 e = e + offset;
91 return e;
92}
93
95template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
96inline constexpr enum_type operator-(enum_type e, int offset)
97{
98 return static_cast<enum_type>(to_underlying(e) - offset);
99}
100
101template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
102inline constexpr enum_type &operator-=(enum_type &e, int offset)
103{
104 e = e - offset;
105 return e;
106}
107
109template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
110inline constexpr auto operator-(enum_type a, enum_type b)
111{
112 return to_underlying(a) - to_underlying(b);
113}
114
116#define DECLARE_ENUM_AS_SEQUENTIAL(enum_type) \
117 template <> struct is_enum_sequential<enum_type> { \
118 static const bool value = true; \
119 };
120
122#define DECLARE_ENUM_AS_BIT_SET(enum_type) \
123 inline constexpr enum_type operator | (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) | to_underlying(m2)); } \
124 inline constexpr enum_type operator & (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
125 inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
126 inline constexpr enum_type& operator |= (enum_type& m1, enum_type m2) { m1 = m1 | m2; return m1; } \
127 inline constexpr enum_type& operator &= (enum_type& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
128 inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
129 inline constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
130
132#define DECLARE_ENUM_AS_ADDABLE(EnumType) \
133 template <typename OtherEnumType, typename = typename std::enable_if<std::is_enum_v<OtherEnumType>, OtherEnumType>::type> \
134 constexpr OtherEnumType operator + (OtherEnumType m1, EnumType m2) { \
135 return static_cast<OtherEnumType>(to_underlying(m1) + to_underlying(m2)); \
136 }
137
144template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
145[[debug_inline]] inline constexpr bool HasFlag(const T x, const T y)
146{
147 return (x & y) == y;
148}
149
155template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
156[[debug_inline]] inline constexpr void ToggleFlag(T &x, const T y)
157{
158 if (HasFlag(x, y)) {
159 x &= ~y;
160 } else {
161 x |= y;
162 }
163}
164
166template <typename Tstorage, typename Tenum, Tenum Tend_value>
168 static constexpr Tstorage value = std::numeric_limits<Tstorage>::max() >> (std::numeric_limits<Tstorage>::digits - to_underlying(Tend_value));
169};
170
179template <typename Tenum, typename Tstorage, Tenum Tend_value = Tenum{std::numeric_limits<Tstorage>::digits}>
180class EnumBitSet : public BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage, EnumBitSetMask<Tstorage, Tenum, Tend_value>::value> {
182public:
183 using EnumType = BaseClass::ValueType;
184
185 constexpr EnumBitSet() : BaseClass() {}
186 constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
187 explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data) {}
188
193 constexpr EnumBitSet(std::initializer_list<const Tenum> values) : BaseClass()
194 {
195 for (const Tenum &value : values) {
196 this->Set(value);
197 }
198 }
199
200 constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
201
202 static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); }
203};
204
211template <typename Container, typename Index>
212class EnumClassIndexContainer : public Container {
213public:
214 Container::reference at(size_t pos) { return this->Container::at(pos); }
215 Container::reference at(const Index &pos) { return this->Container::at(to_underlying(pos)); }
216
217 Container::const_reference at(size_t pos) const { return this->Container::at(pos); }
218 Container::const_reference at(const Index &pos) const { return this->Container::at(to_underlying(pos)); }
219
220 Container::reference operator[](size_t pos) { return this->Container::operator[](pos); }
221 Container::reference operator[](const Index &pos) { return this->Container::operator[](to_underlying(pos)); }
222
223 Container::const_reference operator[](size_t pos) const { return this->Container::operator[](pos); }
224 Container::const_reference operator[](const Index &pos) const { return this->Container::operator[](to_underlying(pos)); }
225};
226
227#endif /* ENUM_TYPE_HPP */
Base for bitset types that accept strong types, ones that need some casting like StrongType and enum ...
Base for bit set wrapper.
Tstorage data
Bitmask of values.
Tvalue_type ValueType
Value type of this BaseBitSet.
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:50
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:17
constexpr enum_type & operator++(enum_type &e)
Prefix increment.
Definition enum_type.hpp:33
constexpr bool is_scoped_enum_v
Implementation of std::is_scoped_enum_v (from C++23)
Definition enum_type.hpp:20
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)
Sub integer.
Definition enum_type.hpp:96
constexpr enum_type operator+(enum_type e, int offset)
Add integer.
Definition enum_type.hpp:82
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:24
Trait to enable prefix/postfix incrementing operators.
Definition enum_type.hpp:73