GCC 16 ships C++20 as the new default, major vectorizer improvements, C++26 reflection, and several ABI changes in libstdc++.
Key Takeaways
C++20 default: -std=gnu++20 replaces -std=gnu++17; projects on older standards must add explicit -std= flags or port.
C++26 reflection lands behind -std=c++26 -freflection, enabling compile-time introspection via P2996R13; contracts (P2900R14) and constexpr exceptions (P3068R5) also included.
libstdc++ ABI breaks: std::variant, atomic waiting, std::format args, std::partial_ordering, and several range adaptors changed layout; C++20 components from older GCC are not binary-compatible.
Vectorizer gains: uncounted loop vectorization, mutual peeling for alignment, and early-break loop optimization for reduced induction overhead.
Porting caveats: int8_t is now signed char on Solaris, JSON diagnostic format removed (use SARIF), and _REENTRANT no longer predefined with -pthread on Solaris.
Hacker News Comment Review
Commenters noted GCC’s annual release cadence is underappreciated; the compiler has shipped on a predictable schedule for years without much fanfare.
Practical concern raised about real-world porting friction: some packages fail to compile under GCC 16 trunk while building fine under GCC 15, suggesting downstream breakage before distros stabilize.
std::start_lifetime_as<T> (P2590R2) highlighted as an underrated addition for zero-copy I/O code, replacing common UB type-punning patterns in buffer-handling code.
Notable Comments
@gavinray: flags std::start_lifetime_as<T> as the correct non-UB replacement for pointer type-punning in zero-copy I/O buffer code – expects low adoption despite importance.
@xzstas: already using C++26 reflection from Debian sid trunk for ser-des; notes lack of an LSP server in the GCC ecosystem as a practical gap.