diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index c8a85c7bba..8f5d176257 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -718,7 +718,7 @@ static void HandleBankruptcyTakeover(Company *c) } /* Did we ask everyone for bankruptcy? If so, bail out. */ - if (c->bankrupt_asked == std::numeric_limits::max()) return; + if (c->bankrupt_asked.All()) return; Company *best = nullptr; int32_t best_performance = -1; @@ -736,7 +736,7 @@ static void HandleBankruptcyTakeover(Company *c) /* Asked all companies? */ if (best_performance == -1) { - c->bankrupt_asked = std::numeric_limits::max(); + c->bankrupt_asked.Set(); return; } diff --git a/src/core/base_bitset_type.hpp b/src/core/base_bitset_type.hpp index 74201dec77..e313c9a2c9 100644 --- a/src/core/base_bitset_type.hpp +++ b/src/core/base_bitset_type.hpp @@ -19,17 +19,28 @@ * @tparam Tvalue_type Type of values to wrap. * @tparam Tstorage Storage type required to hold values. */ -template +template ::max()> class BaseBitSet { public: using ValueType = Tvalue_type; ///< Value type of this BaseBitSet. using BaseType = Tstorage; ///< Storage type of this BaseBitSet, be ConvertibleThroughBase + static constexpr Tstorage MASK = Tmask; ///< Mask of valid values. constexpr BaseBitSet() : data(0) {} - explicit constexpr BaseBitSet(Tstorage data) : data(data) {} + explicit constexpr BaseBitSet(Tstorage data) : data(data & Tmask) {} constexpr auto operator <=>(const BaseBitSet &) const noexcept = default; + /** + * Set all bits. + * @returns The bit set + */ + inline constexpr Timpl &Set() + { + this->data = Tmask; + return static_cast(*this); + } + /** * Set the value-th bit. * @param value Bit to set. @@ -97,6 +108,15 @@ public: return (this->data & other.data) == other.data; } + /** + * Test if all of the values are set. + * @returns true iff all of the values are set. + */ + inline constexpr bool All() const + { + return this->data == Tmask; + } + /** * Test if any of the given values are set. * @param other BitSet of values to test. @@ -144,6 +164,15 @@ public: return this->data; } + /** + * Test that the raw value of this bit set is valid. + * @returns true iff the no bits outside the masked value are set. + */ + inline constexpr bool IsValid() const + { + return (this->base() & Tmask) == this->base(); + } + private: Tstorage data; ///< Bitmask of values. }; diff --git a/src/core/enum_type.hpp b/src/core/enum_type.hpp index 961b78f415..61f1e19767 100644 --- a/src/core/enum_type.hpp +++ b/src/core/enum_type.hpp @@ -110,6 +110,12 @@ debug_inline constexpr void ToggleFlag(T &x, const T y) } } +/** Helper template structure to get the mask for an EnumBitSet from the end enum value. */ +template +struct EnumBitSetMask { + static constexpr Tstorage value = std::numeric_limits::max() >> (std::numeric_limits::digits - to_underlying(Tend_value)); +}; + /** * Enum-as-bit-set wrapper. * Allows wrapping enum values as a bit set. Methods are loosely modelled on std::bitset. @@ -119,15 +125,14 @@ debug_inline constexpr void ToggleFlag(T &x, const T y) * @tparam Tend_value Last valid value + 1. */ template ::digits}> -class EnumBitSet : public BaseBitSet, Tenum, Tstorage> { - using BaseClass = BaseBitSet, Tenum, Tstorage>; +class EnumBitSet : public BaseBitSet, Tenum, Tstorage, EnumBitSetMask::value> { + using BaseClass = BaseBitSet, Tenum, Tstorage, EnumBitSetMask::value>; public: 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() : BaseClass() {} constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); } - explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data & MASK) {} + explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data) {} /** * Construct an EnumBitSet from a list of enum values. @@ -142,15 +147,6 @@ public: constexpr auto operator <=>(const EnumBitSet &) const noexcept = default; - /** - * 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->base() & MASK) == this->base(); - } - static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); } }; diff --git a/src/economy.cpp b/src/economy.cpp index 3bc48f42d1..a64a843b4b 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -627,7 +627,7 @@ static void CompanyCheckBankrupt(Company *c) * is no THE-END, otherwise mark the client as spectator to make sure * they are no longer in control of this company. However... when you * join another company (cheat) the "unowned" company can bankrupt. */ - c->bankrupt_asked = std::numeric_limits::max(); + c->bankrupt_asked.Set(); break; } diff --git a/src/engine.cpp b/src/engine.cpp index 99c05a26ac..c36d91fa67 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -744,7 +744,7 @@ void StartupOneEngine(Engine *e, const TimerGameCalendar::YearMonthDay &aging_ym int intro_months = intro_ymd.year.base() * 12 + intro_ymd.month; if (intro_ymd.day > 1) intro_months++; // Engines are introduced at the first month start at/after intro date. e->age = aging_months - intro_months; - e->company_avail = std::numeric_limits::max(); + e->company_avail.Set(); e->flags.Set(EngineFlag::Available); } @@ -885,7 +885,7 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company, int recursion_d Engine *e = Engine::Get(eid); e->preview_company = INVALID_COMPANY; - e->preview_asked = std::numeric_limits::max(); + e->preview_asked.Set(); EnableEngineForCompany(eid, company); @@ -980,7 +980,7 @@ static IntervalTimer _calendar_engines_daily({TimerGameCalend e->preview_company = GetPreviewCompany(e); if (e->preview_company == INVALID_COMPANY) { - e->preview_asked = std::numeric_limits::max(); + e->preview_asked.Set(); continue; } @@ -1109,7 +1109,7 @@ static void NewVehicleAvailable(Engine *e) AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type); /* Now available for all companies */ - e->company_avail = std::numeric_limits::max(); + e->company_avail.Set(); /* Do not introduce new rail wagons */ if (IsWagon(index)) return; diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 0c54fca0e5..f951ae7752 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2051,15 +2051,15 @@ bool AfterLoadGame() /* More companies ... */ for (Company *c : Company::Iterate()) { - if (c->bankrupt_asked.base() == 0xFF) c->bankrupt_asked = std::numeric_limits::max(); + if (c->bankrupt_asked.base() == 0xFF) c->bankrupt_asked.Set(); } for (Engine *e : Engine::Iterate()) { - if (e->company_avail.base() == 0xFF) e->company_avail = std::numeric_limits::max(); + if (e->company_avail.base() == 0xFF) e->company_avail.Set(); } for (Town *t : Town::Iterate()) { - if (t->have_ratings.base() == 0xFF) t->have_ratings = std::numeric_limits::max(); + if (t->have_ratings.base() == 0xFF) t->have_ratings.Set(); for (uint i = 8; i != MAX_COMPANIES; i++) t->ratings[i] = RATING_INITIAL; } } diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index 26aee110ba..5541975b91 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -109,7 +109,7 @@ struct ENGNChunkHandler : ChunkHandler { * Just cancel any previews. */ e->flags.Reset(EngineFlag{4}); // ENGINE_OFFER_WINDOW_OPEN e->preview_company = INVALID_COMPANY; - e->preview_asked = std::numeric_limits::max(); + e->preview_asked.Set(); } } } diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 7f4fa1efa5..3cddab29b1 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -406,7 +406,7 @@ static bool FixTTOEngines() /* Make sure for example monorail and maglev are available when they should be */ if (TimerGameCalendar::date >= e->intro_date && e->info.climates.Test(LandscapeType::Temperate)) { e->flags.Set(EngineFlag::Available); - e->company_avail = std::numeric_limits::max(); + e->company_avail.Set(); e->age = TimerGameCalendar::date > e->intro_date ? (TimerGameCalendar::date - e->intro_date).base() / 30 : 0; } } else { @@ -431,7 +431,7 @@ static bool FixTTOEngines() * if at least one of them was available. */ for (uint j = 0; j < lengthof(tto_to_ttd); j++) { if (tto_to_ttd[j] == i && _old_engines[j].company_avail.Any()) { - e->company_avail = std::numeric_limits::max(); + e->company_avail.Set(); e->flags.Set(EngineFlag::Available); break; } @@ -441,7 +441,7 @@ static bool FixTTOEngines() } e->preview_company = INVALID_COMPANY; - e->preview_asked = std::numeric_limits::max(); + e->preview_asked.Set(); e->preview_wait = 0; e->name = std::string{}; } diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 404f4b0e49..eb2d551dd4 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -724,7 +724,7 @@ protected: */ inline CompanyMask GetOverlayCompanyMask() const { - return Company::IsValidID(_local_company) ? CompanyMask{}.Set(_local_company) : std::numeric_limits::max(); + return Company::IsValidID(_local_company) ? CompanyMask{}.Set(_local_company) : CompanyMask{}.Set(); } /** Blink the industries (if selected) on a regular interval. */