diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b063cbba76..a6d464e473 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -3,6 +3,7 @@ add_files(
alloc_func.hpp
alloc_type.hpp
backup_type.hpp
+ base_bitset_type.hpp
bitmath_func.hpp
convertible_through_base.hpp
endian_func.hpp
diff --git a/src/core/base_bitset_type.hpp b/src/core/base_bitset_type.hpp
new file mode 100644
index 0000000000..07fd3b76c4
--- /dev/null
+++ b/src/core/base_bitset_type.hpp
@@ -0,0 +1,140 @@
+/*
+ * This file is part of OpenTTD.
+ * 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.
+ * 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.
+ * 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 .
+ */
+
+/**
+ * @file base_bitset_type.hpp Base for bitset types that accept strong types,
+ * i.e. types that need some casting like StrongType and enum class.
+ */
+
+#ifndef BASE_BITSET_TYPE_HPP
+#define BASE_BITSET_TYPE_HPP
+
+/**
+ * Base for bit set wrapper.
+ * Allows wrapping strong type values as a bit set. Methods are loosely modelled on std::bitset.
+ * @tparam Tvalue_type Type of values to wrap.
+ * @tparam Tstorage Storage type required to hold values.
+ */
+template
+class BaseBitSet {
+public:
+ using ValueType = Tvalue_type; ///< Value type of this BaseBitSet.
+ using BaseType = Tstorage; ///< Storage type of this BaseBitSet, be ConvertibleThroughBase
+
+ constexpr BaseBitSet() : data(0) {}
+ explicit constexpr BaseBitSet(Tstorage data) : data(data) {}
+
+ constexpr auto operator <=>(const BaseBitSet &) const noexcept = default;
+
+ /**
+ * Set the value-th bit.
+ * @param value Bit to set.
+ * @returns The bit set
+ */
+ inline constexpr Timpl &Set(Tvalue_type value)
+ {
+ this->data |= (1ULL << Timpl::DecayValueType(value));
+ return static_cast(*this);
+ }
+
+ /**
+ * Reset the value-th bit.
+ * @param value Bit to reset.
+ * @returns The bit set
+ */
+ inline constexpr Timpl &Reset(Tvalue_type value)
+ {
+ this->data &= ~(1ULL << Timpl::DecayValueType(value));
+ return static_cast(*this);
+ }
+
+ /**
+ * Flip the value-th bit.
+ * @param value Bit to flip.
+ * @returns The bit set
+ */
+ inline constexpr Timpl &Flip(Tvalue_type value)
+ {
+ if (this->Test(value)) {
+ return this->Reset(value);
+ } else {
+ return this->Set(value);
+ }
+ }
+
+ /**
+ * Test if the value-th bit is set.
+ * @param value Bit to check.
+ * @returns true iff the requested bit is set.
+ */
+ inline constexpr bool Test(Tvalue_type value) const
+ {
+ return (this->data & (1ULL << Timpl::DecayValueType(value))) != 0;
+ }
+
+ /**
+ * Test if all of the values are set.
+ * @param other BitSet of values to test.
+ * @returns true iff all of the values are set.
+ */
+ inline constexpr bool All(const Timpl &other) const
+ {
+ return (this->data & other.data) == other.data;
+ }
+
+ /**
+ * Test if any of the given values are set.
+ * @param other BitSet of values to test.
+ * @returns true iff any of the given values are set.
+ */
+ inline constexpr bool Any(const Timpl &other) const
+ {
+ return (this->data & other.data) != 0;
+ }
+
+ /**
+ * Test if any of the values are set.
+ * @returns true iff any of the values are set.
+ */
+ inline constexpr bool Any() const
+ {
+ return this->data != 0;
+ }
+
+ /**
+ * Test if none of the values are set.
+ * @returns true iff none of the values are set.
+ */
+ inline constexpr bool None() const
+ {
+ return this->data == 0;
+ }
+
+ inline constexpr Timpl operator |(const Timpl &other) const
+ {
+ return Timpl{static_cast(this->data | other.data)};
+ }
+
+ inline constexpr Timpl operator &(const Timpl &other) const
+ {
+ return Timpl{static_cast(this->data & other.data)};
+ }
+
+ /**
+ * Retrieve the raw value behind this bit set.
+ * @returns the raw value.
+ */
+ inline constexpr Tstorage base() const noexcept
+ {
+ return this->data;
+ }
+
+private:
+ Tstorage data; ///< Bitmask of values.
+};
+
+#endif /* BASE_BITSET_TYPE_HPP */
diff --git a/src/core/enum_type.hpp b/src/core/enum_type.hpp
index 12ce318c69..961b78f415 100644
--- a/src/core/enum_type.hpp
+++ b/src/core/enum_type.hpp
@@ -10,6 +10,8 @@
#ifndef ENUM_TYPE_HPP
#define ENUM_TYPE_HPP
+#include "base_bitset_type.hpp"
+
/** Implementation of std::to_underlying (from C++23) */
template
constexpr std::underlying_type_t to_underlying(enum_type e) { return static_cast>(e); }
@@ -117,21 +119,21 @@ debug_inline constexpr void ToggleFlag(T &x, const T y)
* @tparam Tend_value Last valid value + 1.
*/
template ::digits}>
-class EnumBitSet {
+class EnumBitSet : public BaseBitSet, Tenum, Tstorage> {
+ using BaseClass = BaseBitSet, Tenum, Tstorage>;
public:
- using EnumType = Tenum; ///< Enum type of this EnumBitSet.
- using BaseType = Tstorage; ///< Storage type of this EnumBitSet, be ConvertibleThroughBase
+ using EnumType = BaseClass::ValueType;
static constexpr Tstorage MASK = std::numeric_limits::max() >> (std::numeric_limits::digits - to_underlying(Tend_value)); ///< Mask of valid values.
- constexpr EnumBitSet() : data(0) {}
- constexpr EnumBitSet(Tenum value) : data(0) { this->Set(value); }
- explicit constexpr EnumBitSet(Tstorage data) : data(data & MASK) {}
+ constexpr EnumBitSet() : BaseClass() {}
+ constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
+ explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data & MASK) {}
/**
* Construct an EnumBitSet from a list of enum values.
* @param values List of enum values.
*/
- constexpr EnumBitSet(std::initializer_list values) : data(0)
+ constexpr EnumBitSet(std::initializer_list values) : BaseClass()
{
for (const Tenum &value : values) {
this->Set(value);
@@ -140,102 +142,16 @@ public:
constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
- /**
- * Set the enum value.
- * @param value Enum value to set.
- * @returns The EnumBitset
- */
- inline constexpr EnumBitSet &Set(Tenum value)
- {
- this->data |= (1ULL << to_underlying(value));
- return *this;
- }
-
- /**
- * Reset the enum value to not set.
- * @param value Enum value to reset.
- * @returns The EnumBitset
- */
- inline constexpr EnumBitSet &Reset(Tenum value)
- {
- this->data &= ~(1ULL << to_underlying(value));
- return *this;
- }
-
- /**
- * Flip the enum value.
- * @param value Enum value to flip.
- * @returns The EnumBitset
- */
- inline constexpr EnumBitSet &Flip(Tenum value)
- {
- if (this->Test(value)) {
- return this->Reset(value);
- } else {
- return this->Set(value);
- }
- }
-
- /**
- * Test if the enum value is set.
- * @param value Enum value to check.
- * @returns true iff the requested value is set.
- */
- inline constexpr bool Test(Tenum value) const
- {
- return (this->data & (1ULL << to_underlying(value))) != 0;
- }
-
- /**
- * Test if all of the enum values are set.
- * @param other BitSet of enum values to test.
- * @returns true iff all of the enum values are set.
- */
- inline constexpr bool All(const EnumBitSet &other) const
- {
- return (this->data & other.data) == other.data;
- }
-
- /**
- * Test if any of the enum values are set.
- * @param other BitSet of enum values to test.
- * @returns true iff any of the enum values are set.
- */
- inline constexpr bool Any(const EnumBitSet &other) const
- {
- return (this->data & other.data) != 0;
- }
-
- inline constexpr EnumBitSet operator |(const EnumBitSet &other) const
- {
- return EnumBitSet{static_cast(this->data | other.data)};
- }
-
- inline constexpr EnumBitSet operator &(const EnumBitSet &other) const
- {
- return EnumBitSet{static_cast(this->data & other.data)};
- }
-
/**
* Test that the raw value of this EnumBitSet is valid.
* @returns true iff the no bits outside the masked value are set.
*/
inline constexpr bool IsValid() const
{
- return (this->data & MASK) == this->data;
+ return (this->base() & MASK) == this->base();
}
- /**
- * Retrieve the raw value behind this EnumBitSet.
- * @returns the raw value.
- */
- inline constexpr Tstorage base() const noexcept
- {
- return this->data;
- }
-
-private:
- Tstorage data; ///< Bitmask of enum values.
+ static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); }
};
#endif /* ENUM_TYPE_HPP */