# GitHub Copilot Repository Instructions: C++ Modernization ## Project Context - **Language:** C++ - **Target Standard:** C++23 (Strict enforcement) - **Migration Goal:** Systematically upgrade legacy C++11/C++14/C++17 code to modern C++23 paradigms. ## Core Objective Modernize the codebase incrementally and safely. Preserve existing behavior unless the task explicitly requests functional changes. Prefer small, reviewable refactors that improve correctness, safety, readability, and maintainability. ## Global Migration Principles - Preserve semantics first; modernize second. - Prefer standard C++23 library facilities over custom utilities where equivalent. - Favor compile-time validation, explicit ownership, and strong type safety. - Reduce boilerplate only when readability improves. - Avoid unnecessary churn in code that is already modern and clear. - Keep ABI-sensitive or externally exposed interfaces stable unless breaking changes are explicitly allowed. - For larger migrations, refactor file-by-file or subsystem-by-subsystem. ## Migration Rules ### 1. Type Inference & Variables - Replace explicit types with `auto` where the type is obvious from the initializer. - Do not use `auto` when it obscures important type information or changes value/reference semantics unintentionally. - Prefer `const auto` and `const auto&` where appropriate. - Use structured bindings (`auto [x, y] = ...`) instead of `std::tie`, `.first/.second`, or tuple indexing where it improves clarity. - Prefer uniform initialization where appropriate. ### 2. Memory & Resource Management - Replace raw owning pointers and manual `delete` with `std::unique_ptr` or `std::shared_ptr`. - Prefer `std::unique_ptr` by default; use `std::shared_ptr` only for true shared ownership. - Use `std::make_unique` and `std::make_shared`. - Enforce RAII for all resource management. - Replace manual lifetime management with scoped objects where possible. - Distinguish clearly between owning and non-owning access; prefer references, `std::span`, or observer-style usage for non-owning views. ### 3. Containers, Views & Strings - Use `std::string_view` for read-only string parameters where lifetime safety is guaranteed. - Never introduce dangling `std::string_view`. - Replace `if (items.find(key) != items.end())` with `if (items.contains(key))` where supported. - Prefer `.starts_with()`, `.ends_with()`, and `.contains()` when they improve readability. - Prefer `std::span` for non-owning contiguous views. - Use `std::mdspan` for multidimensional indexing only where it meaningfully improves safety or clarity. - Prefer standard algorithms and ranges over manual loops when they improve readability and maintainability. - Avoid unnecessary copies; prefer move semantics, `emplace`, and views where safe. ### 4. Control Flow & Error Handling - Prefer early returns over deep nesting. - Use `[[nodiscard]]` for functions whose return values should not be ignored. - Modernize `std::optional` usage with `.and_then()`, `.transform()`, and `.or_else()` where this makes the logic clearer. - Replace sentinel values with `std::optional`, strong types, or `std::expected` if supported by the project/toolchain. - Preserve existing exception guarantees and error behavior unless changes are explicitly requested. ### 5. Formatting & Output - Replace `printf` and legacy `` console output with `` where toolchain support exists. - Use `std::print` and `std::println` for standard console output. - If `` is unavailable in the project toolchain, note the limitation and prefer the most modern supported alternative. - Do not mix output styles in the same updated code path without a strong reason. ### 6. Compile-Time Optimization & Templates - Maximize appropriate use of `constexpr`. - Use `consteval` and `constinit` where semantically beneficial. - Replace legacy SFINAE / `std::enable_if` with Concepts and `requires` clauses. - Use `if constexpr` to simplify compile-time branching. - Prefer readable template constraints and diagnostics over complex metaprogramming. ### 7. API & Interface Modernization - Add `noexcept` where correct and useful. - Use `override` consistently for overridden virtual functions. - Use `final` where appropriate. - Prefer `= default` and `= delete` for special member functions. - Prefer `enum class` over unscoped enums where practical. - Replace output parameters with return values or small result structs where this improves clarity and does not break required interfaces. ### 8. Concurrency & Time - Prefer modern standard library concurrency primitives. - Use `std::jthread` instead of `std::thread` where automatic joining and cancellation semantics are beneficial. - Prefer typed `std::chrono` durations and literals over raw integer time values. ## Code Style Enforcement - Avoid C-style macros where `constexpr`, `const`, enums, or inline functions are better. - Never introduce deprecated or removed standard library facilities. - Prefer expressive, self-documenting code over mechanical modernization. - Keep includes minimal and correct. - Avoid hidden lifetime bugs, dangling references, dangling views, and ownership ambiguity. - Preserve repository formatting and local style conventions unless explicitly changing them. ## Safety Constraints - Do not change business logic unless explicitly requested. - Do not silently alter ownership semantics without calling it out. - Do not replace code with newer constructs if the result is harder to read. - Do not introduce C++23 features that are unsupported by the project compiler/toolchain. - Highlight any modernization that may affect ABI, performance, exception behavior, or object lifetime. ## Review Checklist For each proposed migration, verify: - Behavior is preserved. - Ownership and lifetime are clearer and safer. - Readability is improved. - Interface compatibility is maintained unless breaking changes are allowed. - C++23 features are applied only where beneficial. - Toolchain compatibility is respected. - Tests and warnings should still pass after the change. ## Expected Copilot Behavior When modernizing code: 1. Start from the existing implementation and refactor incrementally. 2. Prefer minimal, reviewable patches over broad rewrites. 3. Briefly explain non-trivial modernizations. 4. Call out risky or behavior-adjacent changes explicitly. 5. Provide optional follow-up refactors separately when they are useful but non-essential. 6. Avoid touching unrelated code. ## Preferred Output Format For each migration task, provide: - the modernized code, - a short rationale, - any compatibility/toolchain caveats, - and optional next-step improvements.tes