OpenTTD Source 20250312-master-gcdcc6b491d
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
68
70#define DECLARE_ENUM_AS_BIT_SET(enum_type) \
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) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
73 inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
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& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
76 inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
77 inline constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
78
80#define DECLARE_ENUM_AS_ADDABLE(EnumType) \
81 template <typename OtherEnumType, typename = typename std::enable_if<std::is_enum_v<OtherEnumType>, OtherEnumType>::type> \
82 constexpr OtherEnumType operator + (OtherEnumType m1, EnumType m2) { \
83 return static_cast<OtherEnumType>(to_underlying(m1) + to_underlying(m2)); \
84 }
85
92template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
93debug_inline constexpr bool HasFlag(const T x, const T y)
94{
95 return (x & y) == y;
96}
97
103template <typename T, class = typename std::enable_if_t<std::is_enum_v<T>>>
104debug_inline constexpr void ToggleFlag(T &x, const T y)
105{
106 if (HasFlag(x, y)) {
107 x &= ~y;
108 } else {
109 x |= y;
110 }
111}
112
114template <typename Tstorage, typename Tenum, Tenum Tend_value>
116 static constexpr Tstorage value = std::numeric_limits<Tstorage>::max() >> (std::numeric_limits<Tstorage>::digits - to_underlying(Tend_value));
117};
118
127template <typename Tenum, typename Tstorage, Tenum Tend_value = Tenum{std::numeric_limits<Tstorage>::digits}>
128class EnumBitSet : public BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage, EnumBitSetMask<Tstorage, Tenum, Tend_value>::value> {
130public:
131 using EnumType = BaseClass::ValueType;
132
133 constexpr EnumBitSet() : BaseClass() {}
134 constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
135 explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data) {}
136
141 constexpr EnumBitSet(std::initializer_list<const Tenum> values) : BaseClass()
142 {
143 for (const Tenum &value : values) {
144 this->Set(value);
145 }
146 }
147
148 constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
149
150 static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); }
151};
152
153#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
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:93
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