From 91101d26faad4fb3bd972a282523575d013a45b4 Mon Sep 17 00:00:00 2001 From: Simeon Manolov Date: Sun, 28 Sep 2025 00:48:42 +0300 Subject: [PATCH] Remove std::vector inheritance --- lib/battle/CBattleInfoCallback.cpp | 6 +-- lib/bonuses/Bonus.cpp | 38 ++--------------- lib/bonuses/Bonus.h | 66 +++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index 687c5653c..f33c98207 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -1456,13 +1456,13 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes( const auto multihexAnimation = attacker->getBonusesOfType(BonusType::MULTIHEX_ANIMATION); for (const auto & bonus : *multihexUnit) - at.friendlyCreaturePositions.insert(processTargets(bonus->additionalInfo)); + at.friendlyCreaturePositions.insert(processTargets(bonus->additionalInfo.data())); for (const auto & bonus : *multihexEnemy) - at.hostileCreaturePositions.insert(processTargets(bonus->additionalInfo)); + at.hostileCreaturePositions.insert(processTargets(bonus->additionalInfo.data())); for (const auto & bonus : *multihexAnimation) - at.overrideAnimationPositions.insert(processTargets(bonus->additionalInfo)); + at.overrideAnimationPositions.insert(processTargets(bonus->additionalInfo.data())); if(attacker->hasBonusOfType(BonusType::THREE_HEADED_ATTACK)) at.hostileCreaturePositions.insert(processTargets({2,6})); diff --git a/lib/bonuses/Bonus.cpp b/lib/bonuses/Bonus.cpp index b2f07394a..87bb78d15 100644 --- a/lib/bonuses/Bonus.cpp +++ b/lib/bonuses/Bonus.cpp @@ -36,38 +36,8 @@ CAddInfo::CAddInfo() = default; CAddInfo::CAddInfo(si32 value) { - if(value != CAddInfo::NONE) - push_back(value); -} - -bool CAddInfo::operator==(si32 value) const -{ - switch(size()) - { - case 0: - return value == CAddInfo::NONE; - case 1: - return operator[](0) == value; - default: - return false; - } -} - -bool CAddInfo::operator!=(si32 value) const -{ - return !operator==(value); -} - -si32 & CAddInfo::operator[](size_type pos) -{ - if(pos >= size()) - resize(pos + 1, CAddInfo::NONE); - return vector::operator[](pos); -} - -si32 CAddInfo::operator[](size_type pos) const -{ - return pos < size() ? vector::operator[](pos) : CAddInfo::NONE; + if (value != CAddInfo::NONE) + data_.push_back(value); } std::string CAddInfo::toString() const @@ -79,12 +49,12 @@ JsonNode CAddInfo::toJsonNode() const { if(size() < 2) { - return JsonNode(operator[](0)); + return JsonNode((*this)[0]); } else { JsonNode node; - for(si32 value : *this) + for(si32 value : data_) node.Vector().emplace_back(value); return node; } diff --git a/lib/bonuses/Bonus.h b/lib/bonuses/Bonus.h index ac0c3ea9a..22de0219f 100644 --- a/lib/bonuses/Bonus.h +++ b/lib/bonuses/Bonus.h @@ -29,22 +29,78 @@ using TConstBonusListPtr = std::shared_ptr; using TPropagatorPtr = std::shared_ptr; using TUpdaterPtr = std::shared_ptr; -class DLL_LINKAGE CAddInfo : public std::vector +class DLL_LINKAGE CAddInfo final { public: + using container = std::vector; + using size_type = container::size_type; enum { NONE = -1 }; CAddInfo(); CAddInfo(si32 value); - bool operator==(si32 value) const; - bool operator!=(si32 value) const; + // Inline definitions in the header to avoid missing symbols across TUs + bool operator==(const CAddInfo& other) const noexcept { + return data_ == other.data_; + } - si32 & operator[](size_type pos); - si32 operator[](size_type pos) const; + bool operator!=(const CAddInfo& other) const noexcept { + return !(*this == other); + } + + bool operator==(si32 value) const + { + switch(data_.size()) + { + case 0: + return value == CAddInfo::NONE; + case 1: + return data_[0] == value; + default: + return false; + } + } + + bool operator!=(si32 value) const + { + return !(*this == value); + } + + + si32 & operator[](size_type pos) + { + if(pos >= data_.size()) + data_.resize(pos + 1, CAddInfo::NONE); + return data_[pos]; + } + + si32 operator[](size_type pos) const + { + return pos < data_.size() ? data_[pos] : CAddInfo::NONE; + } std::string toString() const; JsonNode toJsonNode() const; + + // Minimal vector-like facade + size_type size() const noexcept { return data_.size(); } + bool empty() const noexcept { return data_.empty(); } + void push_back(si32 v) { data_.push_back(v); } + void resize(size_type n, si32 fill = CAddInfo::NONE) { data_.resize(n, fill); } + + container::iterator begin() noexcept { return data_.begin(); } + container::iterator end() noexcept { return data_.end(); } + container::const_iterator begin() const noexcept { return data_.begin(); } + container::const_iterator end() const noexcept { return data_.end(); } + + // expose const view for free operators + const container& data() const noexcept { return data_; } + + template + void serialize(H& h) { h & data_; } + +private: + container data_; }; /// Struct for handling bonuses of several types. Can be transferred to any hero