OpenTTD Source 20250529-master-g10c159a79f
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
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 <typename enum_type>
22 static constexpr bool value = false;
23};
24
25template <typename enum_type>
26constexpr bool is_enum_incrementable_v = is_enum_incrementable<enum_type>::value;
27
29template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
30inline constexpr enum_type &operator ++(enum_type &e)
31{
32 e = static_cast<enum_type>(to_underlying(e) + 1);
33 return e;
34}
35
37template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
38inline constexpr enum_type operator ++(enum_type &e, int)
39{
40 enum_type e_org = e;
41 ++e;
42 return e_org;
43}
44
46template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
47inline constexpr enum_type &operator --(enum_type &e)
48{
49 e = static_cast<enum_type>(to_underlying(e) - 1);
50 return e;
51}
52
54template <typename enum_type, std::enable_if_t<is_enum_incrementable_v<enum_type>, bool> = true>
55inline constexpr enum_type operator --(enum_type &e, int)
56{
57 enum_type e_org = e;
58 --e;
59 return e_org;
60}
61
63#define DECLARE_INCREMENT_DECREMENT_OPERATORS(enum_type) \
64 template <> struct is_enum_incrementable<enum_type> { \
65 static const bool value = true; \
66 };
67
69template <typename enum_type>
71 static constexpr bool value = false;
72};
73
74template <typename enum_type>
75constexpr bool is_enum_sequential_v = is_enum_sequential<enum_type>::value;
76
78template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
79inline constexpr enum_type operator+(enum_type e, int offset)
80{
81 return static_cast<enum_type>(to_underlying(e) + offset);
82}
83
84template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
85inline constexpr enum_type &operator+=(enum_type &e, int offset)
86{
87 e = e + offset;
88 return e;
89}
90
92template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
93inline constexpr enum_type operator-(enum_type e, int offset)
94{
95 return static_cast<enum_type>(to_underlying(e) - offset);
96}
97
98template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
99inline constexpr enum_type &operator-=(enum_type &e, int offset)
100{
101 e = e - offset;
102 return e;
103}
104
106template <typename enum_type, std::enable_if_t<is_enum_sequential_v<enum_type>, bool> = true>
107inline constexpr auto operator-(enum_type a, enum_type b)
108{
109 return to_underlying(a) - to_underlying(b);
110}
111
113#define DECLARE_ENUM_AS_SEQUENTIAL(enum_type) \
114 template <> struct is_enum_sequential<enum_type> { \
115 static const bool value = true; \
116 };
117
119#define DECLARE_ENUM_AS_BIT_SET(enum_type) \
120 inline constexpr enum_type operator | (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) | to_underlying(m2)); } \
121 inline constexpr enum_type operator & (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
122 inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
123 inline constexpr enum_type& operator |= (enum_type& m1, enum_type m2) { m1 = m1 | m2; return m1; } \
124 inline constexpr enum_type& operator &= (enum_type& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
125 inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
126 inline constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
127
129#define DECLARE_ENUM_AS_ADDABLE(EnumType) \
130 template <typename OtherEnumType, typename = typename std::enable_if<std::is_enum_v<OtherEnumType>, OtherEnumType>::type> \
131 constexpr OtherEnumType operator + (OtherEnumType m1, EnumType m2) { \
132 return static_cast<OtherEnumType>(to_underlying(m1) + to_underlying(m2)); \
133 }
134
141template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
142debug_inline constexpr bool HasFlag(const T x, const T y)
143{
144 return (x & y) == y;
145}
146
152template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
153debug_inline constexpr void ToggleFlag(T &x, const T y)
154{
155 if (HasFlag(x, y)) {
156 x &= ~y;
157 } else {
158 x |= y;
159 }
160}
161
163template <typename Tstorage, typename Tenum, Tenum Tend_value>
165 static constexpr Tstorage value = std::numeric_limits<Tstorage>::max() >> (std::numeric_limits<Tstorage>::digits - to_underlying(Tend_value));
166};
167
176template <typename Tenum, typename Tstorage, Tenum Tend_value = Tenum{std::numeric_limits<Tstorage>::digits}>
177class EnumBitSet : public BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage, EnumBitSetMask<Tstorage, Tenum, Tend_value>::value> {
179public:
180 using EnumType = BaseClass::ValueType;
181
182 constexpr EnumBitSet() : BaseClass() {}
183 constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
184 explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data) {}
185
190 constexpr EnumBitSet(std::initializer_list<const Tenum> values) : BaseClass()
191 {
192 for (const Tenum &value : values) {
193 this->Set(value);
194 }
195 }
196
197 constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
198
199 static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); }
200};
201
202#endif /* ENUM_TYPE_HPP */
Base for bitset types that accept strong types, i.e.
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.
constexpr enum_type & operator--(enum_type &e)
Prefix decrement.
Definition enum_type.hpp:47
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:17
constexpr enum_type & operator++(enum_type &e)
Prefix increment.
Definition enum_type.hpp:30
constexpr enum_type operator-(enum_type e, int offset)
Sub integer.
Definition enum_type.hpp:93
debug_inline 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)
Add integer.
Definition enum_type.hpp:79
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:21
Trait to enable prefix/postfix incrementing operators.
Definition enum_type.hpp:70