C++20 Migration

C++20 migration plan

Status tracking: phase checklist summary lives on the Core Roadmap. This page keeps implementation detail.

Implementation plan for raising firelands-next from C++17 to C++20.

Status: Phase 1 complete (2026-05-18) — CMAKE_CXX_STANDARD 20 at root; tool targets use cxx_std_20. Phase 2 (incremental feature adoption) open.

Phase 1 checklist ✅

  • Root CMakeLists.txt: CMAKE_CXX_STANDARD 20
  • All tool CMakeLists.txt: cxx_std_20
  • Developer docs and agent guidance updated
  • SPDLOG_USE_STD_FORMAT (bundled fmt in spdlog 1.14.1 fails on C++20 / Apple Clang)
  • Trial build: auth + world on macOS
  • std::span on ByteBuffer (Append/Read/AsSpan/UnreadSpan)
  • Boost.Asio C++20 coroutines across infrastructure/network/
  • Trial builds on full compiler matrix (Linux GCC/Clang, Windows MSVC)
  • Phase 2 remaining: designated initializers, using enum

Goals

GoalRationale
Single standardOne CMAKE_CXX_STANDARD for auth, world, libraries, tests, tools
Safer codeC++20 features reduce bugs without changing architecture
PortabilityWindows (MSVC/MinGW), Linux (GCC/Clang), macOS (Apple Clang)
Incremental rolloutFlag flip first, features in follow-up PRs

Non-goals

  • C++23 migration
  • Large refactors “because C++20 allows it”
  • Mandatory std::format everywhere (keep spdlog fmt-style initially)
  • Changing third-party C APIs (MariaDB, Lua, StormLib boundaries)

Why migrate

AreaC++20 benefit
Network / packetsstd::span<const std::byte> — fewer raw pointer + length pairs
Domain / portsconcept for test constraints (optional)
BoilerplateDesignated initializers; using enum for opcodes
Concurrencystd::jthread + stop tokens for new workers
Network I/OCoroutines replace callback chains ( done in infrastructure/network )

Compiler matrix (target)

PlatformCompilerMinimum
LinuxGCC12
LinuxClang15
macOSApple Clang15 (Xcode 15+)
WindowsMSVCVS 2022 17.4+
WindowsMinGWGCC 12+ UCRT

Phase 2 — Feature adoption (incremental)

PriorityFeatureWhere
P1 ✅std::spanshared/network/, ByteBuffer
P1Designated initializersNew structs in domain/, config DTOs
P2using enumOpcode headers in shared/network
P2constexpr expansionPacket sizes, magic constants
P3std::rangesNew code only
P3std::formatNon-hot-path formatting
P4conceptTest doubles in tests/unit/
P4std::jthreadNew background tasks only

Coroutines (network — complete)

All src/infrastructure/network/ I/O uses co_await via AsioAwaitables.h:

ComponentPatterns
AsyncNetworkServerAcceptLoop
AuthSessionReadLoop, WriteLoop
WorldSessionReadLoop, WriteLoop, TimeSyncLoop, deferred spell co_await
RestAuthServerasync_read / async_write
RealmLinkSession / RealmLinkOutboundRead/write + ping loops

Dependency notes

DependencyC++20 riskMitigation
spdlog 1.14.1MediumSPDLOG_USE_STD_FORMAT
FTXUI 5.0.0MediumTrial-build consoles
GoogleTest, yaml-cpp, MariaDB, Lua, StormLibLowC API boundaries unchanged

Coding guidelines (post-migration)

  1. New code may use Phase 2 features; do not mass-restylize working C++17
  2. Hexagonal rules unchanged — no infra headers in domain/
  3. PCH: add C++20 headers to PROJECT_PCH_HEADERS only if measured win
  4. Reviews: reject C++20-only restyle without measurable benefit

Rollback

Revert Phase 1 PR (CMake + doc flags) — code without C++20-only syntax compiles as C++17 again.