From 77249df889fa004b30a8f9da7df7979fe1ef1847 Mon Sep 17 00:00:00 2001 From: Vandomas Date: Sun, 30 Aug 2026 00:39:17 +0300 Subject: [PATCH 1/2] Add compat for `std::views::enumerate` (#3289) libc++ does not yet have it. --- rts/Lua/LuaHandleSynced.cpp | 3 ++- rts/Sim/Units/Unit.cpp | 3 ++- rts/System/RangesCompat.h | 48 +++++++++++++++++++++++++++++++++++ rts/System/Sync/DumpState.cpp | 11 ++++---- 4 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 rts/System/RangesCompat.h diff --git a/rts/Lua/LuaHandleSynced.cpp b/rts/Lua/LuaHandleSynced.cpp index fb788e15a0b..b9a7b924887 100644 --- a/rts/Lua/LuaHandleSynced.cpp +++ b/rts/Lua/LuaHandleSynced.cpp @@ -1,5 +1,6 @@ /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ +#include "System/RangesCompat.h" #include "LuaHandleSynced.h" #include "LuaInclude.h" @@ -1220,7 +1221,7 @@ bool CSyncedLuaHandle::ResourceExcess(const std::map & exces for (const auto &[teamID, excess] : excesses) { lua_createtable(L, excess.MAX_RESOURCES, 0); - for (const auto &[resourceID, resource] : std::views::enumerate(excess)) { + for (const auto &[resourceID, resource] : spring::views::enumerate(excess)) { lua_pushnumber(L, resource); lua_rawseti(L, -2, resourceID + 1); } diff --git a/rts/Sim/Units/Unit.cpp b/rts/Sim/Units/Unit.cpp index 9d2f32b304d..44ac4ab71e5 100644 --- a/rts/Sim/Units/Unit.cpp +++ b/rts/Sim/Units/Unit.cpp @@ -1,5 +1,6 @@ /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ +#include "System/RangesCompat.h" #include "UnitDef.h" #include "Unit.h" #include "UnitHandler.h" @@ -965,7 +966,7 @@ static auto SplitResourcePackIntoPositiveNegative (const SResourcePack &pack) { SResourcePack positive {0.0f}, negative {0.0f}; - for (auto [resourceID, value] : std::views::enumerate (pack)) { + for (auto [resourceID, value] : spring::views::enumerate (pack)) { if (value < 0.0f) negative[resourceID] = -value; else diff --git a/rts/System/RangesCompat.h b/rts/System/RangesCompat.h new file mode 100644 index 00000000000..88eaa9a4ca4 --- /dev/null +++ b/rts/System/RangesCompat.h @@ -0,0 +1,48 @@ +/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ + +#ifndef RANGES_COMPAT_H +#define RANGES_COMPAT_H + +#include +#include +#include +#include + +namespace spring::views { + +#ifdef __cpp_lib_ranges_enumerate + +using std::views::enumerate; + +#else + +template auto enumerate(Rng& rng) +{ + struct Iterator { + decltype(std::begin(rng)) it; + std::ptrdiff_t idx; + + // the element half stays a reference, copying it would turn a + // mutating loop into a no-op + auto operator * () const { return std::pair(idx, *it); } + Iterator& operator ++ () { ++it; ++idx; return *this; } + bool operator != (const Iterator& o) const { return it != o.it; } + }; + + struct View { + Rng& rng; + Iterator begin() const { return {std::begin(rng), 0}; } + Iterator end () const { return {std::end (rng), 0}; } + }; + + return View{rng}; +} + +// the view holds a reference, so a temporary would dangle +template void enumerate(Rng&&) = delete; + +#endif + +} + +#endif // RANGES_COMPAT_H diff --git a/rts/System/Sync/DumpState.cpp b/rts/System/Sync/DumpState.cpp index 0293f909105..bb7806973d2 100644 --- a/rts/System/Sync/DumpState.cpp +++ b/rts/System/Sync/DumpState.cpp @@ -1,5 +1,6 @@ /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ +#include "System/RangesCompat.h" #include #include #include @@ -687,15 +688,15 @@ void DumpState(int newMinFrameNum, int newMaxFrameNum, int newFramePeriod, std:: const CTeam* t = teamHandler.Team(a); file << "\t\tteamID: " << t->teamNum << " (controller: " << t->GetControllerName() << ")\n"; - for (const auto &[resourceID, value] : std::views::enumerate(t->res)) + for (const auto &[resourceID, value] : spring::views::enumerate(t->res)) file << "\t\t\tstored[" << resourceID << "]: " << TapFloats(value); - for (const auto &[resourceID, value] : std::views::enumerate(t->resStorage)) + for (const auto &[resourceID, value] : spring::views::enumerate(t->resStorage)) file << "\t\t\tmaxStorage[" << resourceID << "]: " << TapFloats(value); - for (const auto &[resourceID, value] : std::views::enumerate(t->resPull)) + for (const auto &[resourceID, value] : spring::views::enumerate(t->resPull)) file << "\t\t\tpull[" << resourceID << "]: " << TapFloats(value); - for (const auto &[resourceID, value] : std::views::enumerate(t->resIncome)) + for (const auto &[resourceID, value] : spring::views::enumerate(t->resIncome)) file << "\t\t\tincome[" << resourceID << "]: " << TapFloats(value); - for (const auto &[resourceID, value] : std::views::enumerate(t->resExpense)) + for (const auto &[resourceID, value] : spring::views::enumerate(t->resExpense)) file << "\t\t\texpense[" << resourceID << "]: " << TapFloats(value); } #endif From 2722801cb80f8519fca5fa66eca05e6c892cc70f Mon Sep 17 00:00:00 2001 From: 0x12A01DC <213792787+0x12A01DC@users.noreply.github.com> Date: Sat, 29 Aug 2026 23:40:26 +0200 Subject: [PATCH 2/2] Replace deprecated `std::aligned_storage` (#3294) Co-authored-by: devgit283 --- rts/System/MemPoolTypes.h | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/rts/System/MemPoolTypes.h b/rts/System/MemPoolTypes.h index 34e0824d50a..af15588dc2e 100644 --- a/rts/System/MemPoolTypes.h +++ b/rts/System/MemPoolTypes.h @@ -7,6 +7,7 @@ #include #include // memset #include +#include #include #include #include @@ -62,14 +63,16 @@ template struct PassThroughPool { }; // Helper to infer the memory alignment and size from a set of types. -template -#if 0 // doesn't compile on MSVC 19.37 -struct TypesMem { - alignas(alignof(T)...) uint8_t data[std::max({sizeof(T)...})]; -}; -#else -using TypesMem = std::aligned_storage_t< std::max({ sizeof(T)... }), std::max({ alignof(T)... }) >; -#endif +template +inline constexpr size_t TypesMemAlignment = std::max({alignof(T)...}); + +template +inline constexpr size_t TypesMemSize = [] { + constexpr size_t alignment = TypesMemAlignment; + constexpr size_t size = std::max({sizeof(T)...}); + + return ((size + alignment - 1) / alignment) * alignment; +}(); template struct DynMemPool { public: @@ -163,8 +166,8 @@ template struct DynMemPool { }; // Helper to infer the DynMemPool pool parameters from a types. -template -using DynMemPoolT = DynMemPool), alignof(TypesMem)>; +template +using DynMemPoolT = DynMemPool, TypesMemAlignment>; // fixed-size dynamic version // page size per chunk, number of chunks, number of pages per chunk @@ -286,8 +289,8 @@ template struct FixedDynMemPool }; // Helper to infer the FixedDynMemPool pool parameters from a types. -template -using FixedDynMemPoolT = FixedDynMemPool), N, K, alignof(TypesMem)>; +template +using FixedDynMemPoolT = FixedDynMemPool, N, K, TypesMemAlignment>; // fixed-size version. template struct StaticMemPool { @@ -372,8 +375,8 @@ template struct StaticMemPool { }; // Helper to infer the StaticMemPool pool parameters from a types. -template -using StaticMemPoolT = StaticMemPool), alignof(TypesMem)>; +template +using StaticMemPoolT = StaticMemPool, TypesMemAlignment>; // dynamic memory allocator operating with stable index positions