Recent from talks
Contribute something
Nothing was collected or created yet.
C++23
View on WikipediaThis article needs to be updated. (March 2024) |
| C++ language revisions |
|---|
C++23, formally ISO/IEC 14882:2024,[1] is the current open standard for the C++ programming language that follows C++20. The final draft of this version is N4950.[2][3]
In February 2020, at the final meeting for C++20 in Prague, an overall plan for C++23 was adopted:[4][5] planned features for C++23 were library support for coroutines, a modular standard library, executors, and networking.
The first WG21 meeting focused on C++23 was intended to take place in Varna in early June 2020, but was cancelled due to the COVID-19 pandemic,[6][7] as was the November 2020 meeting in New York[8][7] and the February 2021 meeting in Kona, Hawaii.[8] All meetings until November 2022 were virtual while the November 2022 meeting until the final meeting in February 2023 was hybrid.[8] The standard was technically finalized by WG21 at the hybrid meeting in Issaquah in February 2023.[9]
Modern "Hello, world" Example
[edit]After many library changes applied to the working draft, the new "Hello, world" program will be: [1]
import std;
int main() {
std::println("Hello, world!");
}
Features
[edit]Changes that have been accepted into C++23 include:
Language
[edit]- explicit
thisobject parameter[10] if consteval[11]- multidimensional subscript operator[12]
- static call and subscript operators and static lambdas[13][14]
- simplifying implicit move[15]
auto(x)andauto{x}[16]- new preprocessor directives:
- extending the lifetime of some temporaries in range-based for loop[19]
- new standard attribute
[[assume(expression)]][20] - class template argument deduction from inherited constructors[21]
- labels at the end of the compound statement[22]
- alias declarations in init-statements[23]
- literal suffixes for
std::size_tand the corresponding signed type[24] - extended floating-point types with literals (conditionally supported)[25]
- optional
()from nullary lambda expressions[26] - attributes on lambda expressions[27]
constexprchanges:- non-literal variables, labels, and
gotos inconstexprfunctions[28] - allowing
staticandthread_localvariables that are usable in constant expressions inconstexprfunctions[29] constexprfunction does not need its return type and parameter types to be literal type- it is now possible to write a
constexprfunction for which no invocation satisfies the requirements of a core constant expression[30]
- non-literal variables, labels, and
- narrowing contextual conversions to
boolinstatic_assertandif constexpr[31] - trimming whitespaces before line splicing[32]
- make declaration order layout mandated[33]
- delimited escape sequences[34]
- named universal character escapes[35]
- text encoding changes:
- New meaning added to some keywords, such as for
this.[39]
Library
[edit]Standard Library Module Support
[edit]Coroutine Library Support
[edit]- synchronous coroutine
std::generatorfor ranges[41]
General Utilities Support
[edit]- result type
std::expected[42] - monadic operations for
std::optional[43] andstd::expected[44] - utility function
std::to_underlyingto get the underlying value of enum[45] - move-only callable wrapper
std::move_only_function[46] std::forward_like[47]std::invoke_r[48]std::bind_back[49]std::byteswap[50]std::unreachable: a function to mark unreachable code[51]- made
std::tuplecompatible with other tuple-like objects[52] std::basic_common_referencespecialization forstd::reference_wrapperyielding reference types[53]- adding default arguments for
std::pair's forwarding constructor[54]
Compile-time Support
[edit]constexprsupport for:- metaprogramming utilities:
- adding move-only types support for comparison concepts[63]
Iterators, Ranges, and Algorithm Support
[edit]- new range conversion function
std::ranges::to[64] - new constrained ranges algorithm:
- new
std::ranges::range_adaptor_closure, a helper for defining user-defined range adaptor closures[49] - new range adaptors:
std::views::zipand other variantsstd::views::adjacentand other variants[70]std::views::join_with[71]std::views::slidestd::views::chunk[72]std::views::chunk_by[73]std::views::as_rvalue[74]std::views::as_const[75]std::views::repeat[76]std::views::stride[77]std::views::cartesian_product[78]std::views::enumerate[79]
- rectifying constant iterators, sentinels, and ranges, that is,
std::ranges::cbeginand other similar utilities returning constant iterators should be fully guaranteed even for shallow-const views (such asstd::span)[75] - ranges iterators as inputs to non-ranges algorithms[80]
- relaxing range adaptors to allow for move only types[81]
- making multi-param constructors of some views
explicit[82]
Memory Management Support
[edit]std::out_ptrandstd::inout_ptrfor C interoperability[83]std::allocate_at_leastandstd::allocator::allocate_at_least[84]- explicit lifetime management function
std::start_lifetime_asfor implicit-lifetime types[85] - disallowing user specialization of
std::allocator_traits[86]
String and Text Processing Support
[edit]- new member functions and changes in string types:
std::basic_string_view::containsandstd::basic_string::contains[87]- disabling construction from
nullptrforstd::basic_stringandstd::basic_string_view[88] - explicit range constructor for
std::basic_string_view[89] std::basic_string::resize_and_overwrite[90]- rvalue reference overload of
std::basic_string::substrfor efficient slicing[91]
- formatting ranges, tuples, escaped presentation of characters and strings,
std::thread::id, and stacktraces.[92][93][94]
Diagnostic Support
[edit]- stacktrace library[95]
I/O Support
[edit]- formatted output functions
std::printandstd::printlnfrom new header<print>[96] - spanstream library (
std::span-based string stream) from new header<spanstream>[97] - a support for exclusive mode in
std::fstreams[98] std::basic_ostream::operator<<(const volatile void*)[99]
Containers Support
[edit]- multidimensional-span
std::mdspan[100][101][102][103] - constructability and assignability of containers from other compatible ranges[64]
- flat set and flat map container adapters[104][105]
- non-deduction context for allocators in container deduction guides[106]
- heterogeneous erasure overloads for associative containers[107]
- allowing iterator pair construction in stack and queue[108]
- requiring
std::spanandstd::basic_string_viewto be trivially copyable[109]
C-Compatibility Support
[edit]- new header
<stdatomic.h>[110]
Language defect reports
[edit]- C++ identifier syntax using Unicode Standard Annex 31[111]
- allowing duplicate attributes[112]
- changing scope of lambda trailing return type[113]
- making overloaded comparison operators less breaking change[114]
- undeprecating volatile compound assignments[115][116]
- fixing the compatibility and portability of
char8_t[117] - relaxing requirements on
wchar_tto match existing practices[118] - allowing some pointers and references of
thisor unknown origin in constant expressions[119] - introduction of immediate-escalating functions promoted to immediate functions[120]
- allowing
static_assert(false)in uninstantiated template contexts
Library defect reports
[edit]- changes in ranges library:
- conditionally borrowed ranges[121]
- repairing input range adaptors and
std::counted_iterator[122] - relaxing the constraint on
std::ranges::join_view[123] - renamed
std::ranges::split_viewtostd::ranges::lazy_split_viewand newsplit_view[124] - removed
std::default_initializableconstraint from conceptstd::ranges::view[125] - view with ownership and new
std::ranges::owning_view[126] - fixed
std::ranges::istream_view[127]
- changes in text formatting library:
std::basic_format_string[128]- compile-time format string checks
- reducing binary code size of
std::format_to[129] - fixing locale handling in chrono formatters[130]
- improving width estimation[131] and fill character allowances of
std::format[132] - use of forwarding references in format arguments to allow non-const-formattable types[133]
- fully
constexprstd::variantandstd::optional[134] - supporting types derived from
std::variantinstd::visit[135]
Removed features and deprecation
[edit]Removed features:
- Garbage Collection Support and (strict) Pointer Safety[136] (meaning only relaxed pointer safety is to be relied upon[137]). This minimal garbage collection support (and pointer safety, needed for it), was added to C++11 but no compilers have ever supported it so the support was removed in C++23.[138] However, that doesn't mean many GC implementations haven't been used, and continue to be used with C++, such as Boehm GC (and it can also just be used for leak detection in leak detection, when in debug mode), and such GC is often implemented in C++, for other languages to use.
- Mixed wide-string literal concatenation.[139]
- Non-encodable wide character literals and multicharacter wide character literals.[140]
Deprecated features:
Reverted deprecated features:
- Use of comma operator in subscript expressions was no longer deprecated but the semantics has been changed to support overloadable n-adic
operator[]. - C headers (The corresponding
<*.h>headers for compatibility with C)
Published as Technical Specifications
[edit]- Concurrency TS v2[143][further explanation needed]
Compiler support
[edit]- Clang progressively added partial C++23 support from 2021 in version 13 through to version 18 in 2024, available through the option
-std=c++23.[144] - GCC added partial, experimental C++23 support in 2021 in version 11 through the option
-std=c++2bor-std=c++23It also has an option to enable GNU extensions in addition to the experimental C++23 support,-std=gnu++2b.[145]
History
[edit]In the absence of face-to-face WG21 meetings, the following changes were applied after several virtual WG21 meetings, where they were approved by straw polls.
November 2020
[edit]The following were added after the virtual WG21 meeting of 9 November 2020, where they were approved by straw polls:[146]
- Literal suffixes for
std::size_tand the corresponding signed type - A member function
containsforstd::basic_stringandstd::basic_string_view, to check whether or not the string contains a given substring or character - A stacktrace library (
<stacktrace>), based on Boost.Stacktrace - A type trait
std::is_scoped_enum - The header
<stdatomic.h>, for interoperability with C atomics
February 2021
[edit]After the virtual WG21 meeting of 22 February 2021, following features are added where they were approved by straw polls:[147]
- Removing unnecessary empty parameter list
()from lambda expressions. - Repairing input range adaptors and
counted_iterator. - Relax the requirements for
time_point::clock.[148] std::visitfor classes that are derived fromstd::variant.- Locks lock lockables.[149]
- Conditionally borrowed ranges.
std::to_underlying.
June 2021
[edit]After the summer 2021 ISO C++ standards plenary virtual meeting of June 2021, new features and defect reports were approved by straw polls:[150]
- Consteval if (
if consteval). - Narrowing contextual conversions to
bool. - Allowing duplicate attributes.
std::span-based string-stream (<spanstream>).std::out_ptr()andstd::inout_ptr().constexprforstd::optional,std::variant, andstd::type_info::operator==.- Iterators pair constructors for
std::stack(stack) andstd::queue(queue). - Few changes of the ranges library:
- Generalized
starts_withandends_withfor arbitrary ranges. - Renamed
split_viewtolazy_split_viewand newsplit_view. - Relaxing the constraint on
join_view. - Removing
default_initializableconstraint from conceptview. - Range constructor for
std::basic_string_view.
- Generalized
- Prohibiting
std::basic_stringandstd::basic_string_viewconstruction fromnullptr. std::invoke_r.- Improvements on
std::format. - Adding default arguments for
std::pair's forwarding constructor.
October 2021
[edit]After the autumn 2021 ISO C++ standards plenary virtual meeting of October 2021, new features and defect reports were approved by straw polls:[151]
- Non-literal variables, labels, and gotos in
constexprfunctions, but still ill-formed to evaluate them at compile-time. - Explicit
thisobject parameter. - Changes on character sets and encodings.
- New preprocessors:
#elifdefand#elifndef. Both directives were added to C23 (C language update) and GCC 12.[152] - Allowing alias declarations in init-statement.
- Overloading multidimensional subscript operator (e.g.
arr[1, 2]). - Decay copy in language:
auto(x)orauto{x}. - Changes in text formatting library:
- Fixing locale handling in chrono formatters.
- Use of forwarding references in format arguments to allow
std::generator-like types.
- Addition of type alias
std::pmr::stacktracewhich is equivalent tostd::basic_stacktrace<std::pmr::polymorphic_allocator>.[153] - Changes in ranges library:
- Refined definition of a view.
- Replacing function template
std::ranges::istream_viewwith alias templatesstd::ranges::istream_view,std::ranges::wistream_view, and customization point objectstd::views::istream. ziprange adaptor family:zip_viewzip_transform_viewadjacent_view(andstd::views::pairwisebeing equivalent tostd::views::adjacent<2>)adjacent_transform_view(andstd::views::pairwise_transformbeing equivalent tostd::views::adjacent_transform<2>)
std::move_only_function.- Monadic operations for
std::optional. - Member function template
std::basic_string::resize_and_overwrite. - Printing
volatilepointers (volatile T*). std::byteswap.- Heterogeneous erasure overloads for associative containers.
- Every specialization of
std::spanandstd::basic_string_viewis trivially copyable. - Adding conditional
noexceptspecifications tostd::exchange.[154] - Revamped specification and use of integer-class types.[155]
- Clarify C headers. "The headers are not useful in code that is only required to be valid C++. Therefore, the C headers should be provided by the C++ standard library as a fully-supported, not deprecated part, but they should also be discouraged for use in code that is not polyglot interoperability code. [..] This proposal makes the C headers no longer deprecated, so there is no formal threat of future removal. The effective discouragement to use the C headers in pure C++ code is now spelled out explicitly as normative discouragement."[156]
February 2022
[edit]After the virtual WG21 meeting of 7 February 2022, the following features are added where they were approved by straw polls:[157]
- Allowed attributes on the function call operator of a lambda
std::expectedconstexprforcmathandcstdlib- Function to mark unreachable code
ranges::to- A type trait to detect reference binding to temporary
- Making
std::unique_ptrconstexpr - Pipe support for user-defined range adaptors
ranges::iota,ranges::shift_leftandranges::shift_rightviews::join_with- Windowing range adaptors:
views::chunkandviews::slide views::chunk_by
July 2022
[edit]After the virtual WG21 meeting of 25 July 2022, the following features and defect reports are added where they were approved by straw polls:[158]
- Made rewriting equality in expressions less of a breaking change.
- Reverted the deprecation of bitwise assignment to
volatilevariables. - Added the
#warningpreprocessor directive. - Removed non-encodable wide character literals and multicharacter wide character literals.
- Allowed labels to appear at the end of compound statements.
- Added escape sequences delimited with curly braces for octal and hexadecimal numbers and universal character names.
- Allowed
constexprfunctions to never be constant expressions. - Simplified some implicit move rules from C++20 and allowed implicit move when returning an rvalue reference.
- Add a way to specify unicode characters by name. For example,
U'\N{LATIN CAPITAL LETTER A WITH MACRON}' // Equivalent to U'\u0100' - Allowed
operator()and lambdas to bestatic. - Allowed the
thispointer and references of unknown origin to appear in constant expressions. - Allowed implementations to define extended floating-point types in addition to the three standard floating-point types. Added the type aliases
std::float16_t,std::float32_t,std::float64_t,std::float128_t,std::bfloat16_tfor these extended types accessible through the header<stdfloat>, their corresponding literal suffixesf16f32f64f128bf16orF16F32F64F128BF16and added overloads to various standard library functions that take floats as arguments. - Added the
[[assume(expression)]]attribute which allows the compiler to assume the provided expression is true to allow optimizations. - Made support for UTF-8 source files mandatory, providing a portable encoding for source files.
- Allowed arrays of
charandunsigned charto be initialized with UTF-8 string literals. - Removed the requirement that
wchar_tcan encode all characters of the extended character set, in effect allowing UTF-16 to be used for wide string literals. - Added
std::mdspan, a multidimensional array view analogous tostd::span. flat_mapandflat_setwere added to the standard library.- Added the
std::printandstd::printlnfunctions for printing formatted text to stdout. - Provide the named modules
stdandstd.compatfor importing the standard library. - Added support for exclusive mode
fstreams, analogous to the "x" flag infopen. - Allowed
std::formatto handle ranges, tuples, and other containers. - Added
std::forward_like. - Made
std::string::substruse move semantics. - Added
std::generatorwhich implements a coroutine generator that modelsstd::ranges::input_range views::cartesian_product,views::repeat,views::stride,views::as_const,views::as_rvalue.- Added new algorithms:
ranges::find_last,ranges::contains, and ranges fold algorithms. - Made
std::tuplecompatible with other tuple-like objects. - Explicit lifetime management for implicit-lifetime types.
- Made
std::bitsetand integral overloads ofstd::to_charsandstd::from_charsconstexpr-compatible. - Adding move-only types support for comparison concepts.
- Ranges iterators as inputs to non-ranges algorithms.
- Relaxing range adaptors to allow for move-only types.
November 2022
[edit]After the hybrid WG21 meeting of 7 November 2022, the following features and defect reports are added where they were approved by straw polls:[159]
- Allowed
operator[]to bestatic. - Allowed
staticandthread_localvariables to appear inconstexprfunctions if they are usable in constant expressions. constevalpropagates upwards, that is, certain existingconstexprfunctions becomeconstevalfunctions when those functions can already only be invoked during compile time.- Extended the lifetime of temporaries that appear in the for-range-initializer of a range-based
forloop to cover the entire loop. - Reverted the deprecation of (all, not just bitwise) compound assignment to
volatilevariables. - Monadic functions for
std::expected. - Synchronize the output of
std::printwith the underlying stream if the native Unicode API is used.[160]
February 2023
[edit]After the final hybrid WG21 meeting of 6-11 February 2023, the following features and defect reports are added where they were approved by straw polls:[161]
- Referencing the Unicode Standard.[162]
- Stashing stashing iterators for proper flattening.[163]
views::enumerate- making multi-param constructors of views explicit
- relaxing ranges just a smidge
- escaping improvements in
std::format - improving
std::format's width estimation std::formatfill character allowances- formatting
thread::idandstacktrace - A type trait
std::is_implicit_lifetime std::common_reference_tofstd::reference_wrappershould be a reference type- disallowing user specialization of
std::allocator_traits std::pmr::generator- deprecating
std::numeric_limits::has_denorm std::barrier's phase completion guarantees
References
[edit]- ^ "ISO/IEC 14882:2024 Programming languages — C++". iso.org.
- ^ "Working Draft, Standard for Programming Language C++" (PDF). Open Standards. ISO/IEC. 2023-05-10. Archived (PDF) from the original on Feb 16, 2024.
- ^ "N4951 Editors' Report: Programming Languages - C++". Open Standards. 2023-05-10. Archived from the original on 2023-06-05.
- ^ Dusíková, Hana (2019-11-06). "N4817: 2020 Prague Meeting Invitation and Information" (PDF). Open Standards. Archived (PDF) from the original on 2019-12-29. Retrieved 2020-02-13.
- ^ Voutilainen, Ville (2019-11-25). "To boldly suggest an overall plan for C++23". Open Standards. Archived from the original on 2019-12-24. Retrieved 2020-02-13.
- ^ Lelbach, Bryce Adelstein; Winters, Titus; Fracassi, Fabio; Baker, Billy; Liber, Nevin; Bastien, JF; Stone, David; Ballo, Botond; Keane, Erich; Honermann, Tom (2020-04-20). "P2145R0: Evolving C++ Remotely". Open Standards. Archived from the original on Feb 12, 2024.
- ^ a b Sutter, Herb (29 July 2020). "Business Plan and Convener's Report: ISO/IEC JTC1/SC22/WG21 (C++)" (PDF).
- ^ a b c "Upcoming Meetings, Past Meetings : Standard C++". isocpp.org.
- ^ "C++23 "Pandemic Edition" is complete (Trip report: Winter ISO C++ standards meeting, Issaquah, WA, USA)". herbsutter.com. 13 February 2023.
- ^ Gašper Ažman; Sy Brand; Ben Deane; Barry Revzin (2021-07-12). "Deducing this".
- ^ Barry Revzin; Richard Smith; Andrew Sutton; Daveed Vandevoorde (2021-03-22). "if consteval".
- ^ Mark Hoemmen; Daisy Hollman; Corentin Jabot; Isabella Muerte; Christian Trott (2021-09-14). "Multidimensional subscript operator" (PDF).
- ^ "static operator()". 2022-04-08.
- ^ "static operator[]" (PDF). 2022-11-11.
- ^ "Simpler implicit move". 2022-03-23.
- ^ Zhihao Yuan (2021-07-12). "auto(x): decay-copy in the language".
- ^ Melanie Blower (2021-04-30). "Add support for preprocessing directives elifdef and elifndef" (PDF).
- ^ Aaron Ballman (2022-01-13). "Support for #warning" (PDF).
- ^ "Wording for P2644R1 Fix for Range-based for Loop". 2022-11-11.
- ^ "Portable assumptions" (PDF). 2022-04-22.
- ^ Timur Doumler (2022-05-20). "Wording for class template argument deduction from inherited constructors" (PDF).
- ^ "Labels at the end of compound statements (C compatibility)" (PDF). 2022-01-13.
- ^ Jens Maurer (2021-04-13). "Extend init-statement to allow alias-declaration".
- ^ JeanHeyd Meneide; Rein Halbersma (2019-11-24). "Literal Suffix for (signed) size_t".
- ^ "Extended floating-point types and standard names". 2022-04-22.
- ^ Alex Christensen; JF Bastien (2020-12-11). "P1102R2: Down with ()!".
- ^ "Attributes on Lambda-Expressions" (PDF).
- ^ Ville Voutilainen (2021-07-12). "Non-literal variables (and labels and gotos) in constexpr functions".
- ^ "Permitting
static constexprvariables inconstexprfunctions". 2022-11-07. - ^ "Relaxing some constexpr restrictions". 2022-01-27.
- ^ Andrzej Krzemieński (2021-04-12). "Narrowing contextual conversions to bool".
- ^ Corentin Jabot (2021-04-13). "Trimming whitespaces before line splicing" (PDF).
- ^ Pal Balog (2021-04-02). "Make declaration order layout mandated" (PDF).
- ^ "Delimited escape sequences" (PDF). 2022-02-25.
- ^ "Named universal character escapes". 2022-03-25.
- ^ "Support for UTF-8 as a portable source file encoding" (PDF). 2022-07-01.
- ^ Corentin Jabot (2021-09-14). "Consistent character literal encoding" (PDF).
- ^ Jens Maurer (2021-09-21). "Character sets and encodings".
- ^ "C++ keywords - cppreference.com". en.cppreference.com. Retrieved 2025-07-27.
- ^ "Standard Library Modules std and std.compat" (PDF).
- ^ "(std::generator: Synchronous Coroutine Generator for Ranges)" (PDF).
- ^ Vicente Botet; JF Bastien; Jonathan Wakely (2022-01-07). "std::expected".
- ^ Sy Brand (2021-04-27). "Monadic operations for std::optional".
- ^ Jeff Garland (2022-09-28). "P2505R5 Monadic Functions for
std::expected". - ^ JeanHeyd Meneide (2021-01-22). "std::to_underlying for enumerations".
- ^ Matt Calabrese; Ryan McDougall (2021-07-09). "move_only_function".
- ^ Gašper Ažman (2022-05-13). "std::forward_like" (PDF).
- ^ Zhihao Yuan (2020-04-29). "invoke_r".
- ^ a b Barry Revzin (2021-12-17). "Pipe support for user-defined range adaptors".
- ^ Isabella Muerte; Corentin Jabot (2021-09-17). "Byteswapping for fun&&nuf".
- ^ Melissa Mears; Jens Maurer (2021-10-15). "Function to mark unreachable code" (PDF).
- ^ Corentin Jabot (2022-07-15). "Compatibility between tuple, pair and tuple-like objects" (PDF).
- ^ Hui Xie; S. Levent Yilmaz; Tim Song (2023-02-07). "common_reference_t of reference_wrapper Should Be a Reference Type".
- ^ "Wording for P2644R1 Fix for Range-based for Loop". 2022-11-11.
- ^ Peter Dimov (2021-05-01). "Making std::type_info::operator== constexpr".
- ^ Daniil Goncharov (2022-06-25). "A more constexpr bitset" (PDF).
- ^ Andreas Fertig (2021-11-06). "Making std::unique_ptr constexpr" (PDF).
- ^ Edward J. Rosten; Oliver J. Rosten (2021-11-12). "constexpr for <cmath> and <cstdlib>" (PDF).
- ^ Daniil Goncharov; Alexander Karaev (2021-09-18). "Add Constexpr Modifiers to Functions to_chars and from_chars for Integral Types in <charconv> Header" (PDF).
- ^ Juan Alday (2020-10-12). "A proposal for a type trait to detect scoped enumerations" (PDF).
- ^ Timur Doumler; Vittorio Romeo (2022-11-11). "A trait for implicit lifetime types" (PDF).
- ^ Tim Song (2021-10-13). "A type trait to detect reference binding to temporary".
- ^ Justin Bassett (2022-07-02). "Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with" (PDF).
- ^ a b Corentin Jabot; Eric Niebler; Casey Carter (2022-01-21). "Conversions from ranges to containers" (PDF).
- ^ Christopher Di Bella (2021-02-19). "starts_with and ends_with".
- ^ Christopher Di Bella (2021-04-16). "std::ranges::contains".
- ^ Zach Laine (2022-06-17). "find_last" (PDF).
- ^ Tim Song (2021-12-05). "ranges::iota, ranges::shift_left, and ranges::shift_right".
- ^ Barry Revzin (2022-04-22). "ranges::fold".
- ^ Tim Song (2021-06-11). "zip".
- ^ Barry Revzin (2022-01-28). "views::join_with".
- ^ Tim Song (2021-12-05). "Windowing range adaptors: views::chunk and views::slide".
- ^ Tim Song (2021-11-19). "views::chunk_by".
- ^ Barry Revzin (2022-02-14). "views::as_rvalue".
- ^ a b Barry Revzin (2022-06-17). "cbegin should always return a constant iterator".
- ^ Michał Dominiak (2022-07-13). "views::repeat".
- ^ Christopher Di Bella; Tim Song (2022-07-08). "stride_view".
- ^ Sy Brand; Michał Dominiak (2022-07-13). "views::cartesian_product".
- ^ Corentin Jabot (2022-12-07). "views::enumerate" (PDF).
- ^ David Olsen (2022-04-22). "Ranges iterators as inputs to non-Ranges algorithms".
- ^ Michał Dominiak (2022-07-13). "Relaxing range adaptors to allow for move only types".
- ^ Ville Voutilainen (2022-11-12). "Making multi-param constructors of views explicit".
- ^ JeanHeyd Meneide; Todor Buyukliev; Isabella Muerte (2021-04-15). "out_ptr - a scalable output pointer abstraction".
- ^ Jonathan Wakely; Chris Kennelly (2021-01-22). "Providing size feedback in the Allocator interface".
- ^ Timur Doumler; Richard Smith (2022-07-15). "Explicit lifetime management" (PDF).
- ^ Pablo Halpern (2023-02-08). "Disallow User Specialization of allocator_traits".
- ^ Wim Leflere; Paul Fee (2020-06-13). "string contains function".
- ^ Yuriy Chernyshov (2020-09-06). "A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr".
- ^ Corentin Jabot (2021-03-17). "Range constructor forstd::string_view 2: Constrain Harder" (PDF).
- ^ Chris Kennelly; Mark Zeren (2021-09-14). "basic_string::resize_and_overwrite".
- ^ "std::string::substr() &&".
- ^ "Formatting Ranges". 16 May 2022.
- ^ Barry Revzin (2022-07-15). "Improve default container formatting".
- ^ Corentin Jabot; Victor Zverovich (2023-02-09). "Formatting thread::id and stacktrace" (PDF).
- ^ Alexey Gorgurov; Antony Polukhin (2020-09-16). "A Proposal to add stacktrace library".
- ^ "Formatted output".
- ^ Peter Sommerlad (2021-02-26). "A strstream replacement using span<charT> as buffer" (PDF).
- ^ "Support exclusive mode for fstreams".
- ^ Bryce Adelstein Lelbach (2021-09-25). "Printing volatile Pointers".
- ^ "MDSPAN". 13 July 2022.
- ^ "index_type & size_type in mdspan" (PDF).
- ^ "
mdspan: renamepointerandcontiguous". 15 June 2022. - ^ "Add the missing
emptytomdspan". - ^ "A Standard flat_map" (PDF).
- ^ "A Standard flat_set" (PDF).
- ^ Arthur O'Dwyer; Mike Spertus (2021-03-14). "Stop overconstraining allocators in container deduction guides".
- ^ Konstantin Boyarinov; Sergey Vinogradov; Ruslan Arutyunyan (2020-12-15). "Heterogeneous erasure overloads for associative containers".
- ^ Corentin Jabot (2021-03-05). "Iterators pair constructors for stack and queue" (PDF).
- ^ Nevin Liber (2021-03-19). "Require span & basic_string_view to be TriviallyCopyable" (PDF).
- ^ Hans-J. Boehm (2020-10-23). "P0943R6: Support C atomics in C++".
- ^ Steve Downey; Zach Laine; Tom Honermann; Peter Bindels; Jens Maurer (2021-04-12). "C++ Identifier Syntax using Unicode Standard Annex 31".
- ^ Erich Keane (2020-07-02). "Allow Duplicate Attributes" (PDF).
- ^ Barry Revzin (2021-09-14). "Change scope of lambda trailing-return-type".
- ^ "The Equality Operator You Are Looking For". 2022-01-13.
- ^ "De-deprecating volatile compound operations" (PDF).
- ^ "Core Language Working Group NB comment resolutions for the November, 2022 meeting : 2654. Un-deprecation of compound volatile assignments".
- ^ "
char8_tCompatibility and Portability Fix". 2022-06-17. - ^ "Relax requirements on
wchar_tto match existing practices" (PDF). 2022-07-15. - ^ "Using unknown pointers and references in constant expressions". 8 April 2022.
- ^ "
constevalneeds to propagate up". 2022-11-11. - ^ Barry Revzin (2020-02-19). "Conditionally borrowed ranges".
- ^ Tim Song (2021-01-12). "Repairing input range adaptors and counted_iterator".
- ^ Tim Song (2021-05-06). "join_view should join all views of ranges".
- ^ Barry Revzin (2021-03-05). "Superior String Splitting".
- ^ Barry Revzin (2021-05-14). "Views should not be required to be default constructible".
- ^ Barry Revzin; Tim Song (2021-08-15). "What is a view?".
- ^ Nicolai Josuttis (2021-09-24). "Fix istream_view" (PDF).
- ^ Barry Revzin (2022-01-18). "Expose std::basic-format-string<charT, Args...>".
- ^ Victor Zverovich (2021-02-05). "std::format improvements".
- ^ Victor Zverovich; Corentin Jabot (2021-09-11). "Fixing locale handling in chrono formatters".
- ^ Corentin Jabot (2022-12-02). "format's width estimation is too approximate and not forward compatible" (PDF).
- ^ Tom Honermann (2023-02-08). "std::format() fill character allowances".
- ^ Victor Zverovich (2021-09-24). "Add support for std::generator-like types to std::format".
- ^ Barry Revzin (2021-02-11). "Missing constexpr in std::optional and std::variant".
- ^ Barry Revzin (2020-10-30). "Inheriting from std::variant".
- ^ "std::pointer_safety - cppreference.com". en.cppreference.com. Retrieved 2024-12-09.
- ^ "[basic.stc.dynamic.safety]". timsong-cpp.github.io. Retrieved 2024-12-09.
- ^ JF Bastien; Alisdair Meredith (2021-04-16). "Removing Garbage Collection Support".
- ^ Jens Maurer (2021-04-12). "Mixed string literal concatenation".
- ^ "Remove non-encodable wide character literals and multicharacter wide character literals" (PDF).
- ^ CJ Johnson (2021-11-22). "Deprecate std::aligned_storage and std::aligned_union" (PDF).
- ^ Matthias Kretz (2022-11-08). "Deprecate numeric_limits::has_denorm" (PDF).
- ^ "Programming Languages — Technical specification for C++ extensions for concurrency 2" (PDF).
- ^ "C++ Support in Clang".
- ^ "C++ Standards Support in GCC - GNU Project".
- ^ Ranns, Nina (2020-11-19). "WG21 2020-11 Virtual Meeting: Minutes of Meeting" (PDF).
- ^ Ranns, Nina (2021-02-22). "WG21 2021-02 Virtual Meeting: Minutes of Meeting" (PDF).
- ^ Alexey Dmitriev; Howard Hinnant (2020-10-22). "Relax Requirements for time_point::clock".
- ^ Tim Song (2020-11-13). "Locks lock lockables".
- ^ Ranns, Nina (2021-06-07). "WG21 2021-06 Virtual Meeting Minutes of Meeting" (PDF).
- ^ Ranns, Nina (2021-10-04). "WG21 2021-10 Virtual Meeting Minutes of Meeting" (PDF).
- ^ "GCC 12 Adds Support For New #elifdef #elifndef Directives". phoronix. May 12, 2021. Archived from the original on December 27, 2022.
- ^ Steve Downey (2021-06-14). "Add a pmr alias for std::stacktrace".
- ^ Giuseppe D'Angelo (2021-06-28). "Add a conditional noexcept specification to std::exchange".
- ^ Tim Song (2021-08-06). "Cleaning up integer-class types".
- ^ Thomas Köppe (2021-06-11). "Clarifying the status of the "C headers"".
- ^ Ranns, Nina (2022-02-07). "WG21 2022-02 Virtual Meeting: Minutes of Meeting" (PDF).
- ^ Ranns, Nina (2022-08-09). "WG21 2022-07 Virtual Meeting: Minutes of Meeting" (PDF).
- ^ Ranns, Nina (2022-12-05). "WG21 2022-11 Hybrid Meeting: Minutes of Meeting" (PDF).
- ^ Victor Zverovich (2022-11-08). "Should the output of std::print to a terminal be synchronized with the underlying stream?".
- ^ Ranns, Nina (2023-03-06). "WG21 2023-02 Hybrid Meeting: Minutes of Meeting" (PDF).
- ^ Corentin Jabot (2023-02-09). "Referencing The Unicode Standard" (PDF).
- ^ Tim Song (2023-01-31). "Stashing stashing iterators for proper flattening".
External links
[edit]- Compiler support for C++23 features - cppreference.com
C++23
View on GrokipediaCore Language Enhancements
C++23 introduces several refinements to the language syntax and semantics to address modern programming needs. Notable additions include support for explicit object member functions (also known as "explicit this"), which allow non-static member functions to explicitly declare their object parameter for improved clarity in generic code and forwarding scenarios.[2] The standard also adds multidimensional subscript operators, enablingoperator[] to accept multiple arguments for more intuitive access to multi-dimensional data structures like arrays or matrices.[2] Other key language features encompass new preprocessing directives #elifdef and #elifndef for conditional compilation based on macro definitions, the auto(x) decay-copying declaration for initializing variables with decayed types, and explicit lifetime extension mechanisms to prevent dangling references in temporary expressions.[2] Additionally, C++23 improves Unicode support for better handling of international text and extends constexpr evaluation to more library functions, allowing compile-time computations in a broader range of contexts.[2]
Standard Library Improvements
The C++23 standard library receives significant updates focused on usability and efficiency, including the introduction of standard library modules that export the core library contents (excluding macros) to facilitate faster compilation and better encapsulation in modular codebases.[2] New types such asstd::expected provide a standardized way to handle errors and optional results, similar to monadic patterns in other languages, while std::generator supports coroutine-based iteration for lazy evaluation and asynchronous data production.[2] Library enhancements also feature string formatting and printing facilities inspired by std::format from C++20 but expanded for more flexible output, new container and view types like std::mdspan for multi-dimensional arrays, and algorithms optimized for ranges.[2] Further additions include the <spanstream> header for stream-like operations on spans and the std::stacktrace library for capturing and inspecting call stacks at runtime.[3]
These changes deliver targeted advancements in productivity and reliability for systems programming, embedded development, and high-performance applications.[2] Compiler support for C++23 features is progressively rolling out in major implementations like GCC, Clang, and MSVC, with full conformance expected in subsequent releases.[4]
Introduction
Overview
C++23 is the current ISO standard for the C++ programming language, formally designated as ISO/IEC 14882:2024 and published in October 2024.[1] The technical work on the standard was completed in February 2023 by the ISO/IEC JTC1/SC22/WG21 committee, marking the culmination of efforts to evolve the language while maintaining backward compatibility.[5] This edition succeeds C++20 and represents a measured advancement in the language's development. The primary goals of C++23 include enhancing executability through better integration of existing features, simplifying common programming patterns to improve developer productivity, and bolstering compile-time capabilities for more efficient code generation.[6] It also prioritizes the incorporation of prior Technical Specifications, such as modules and ranges, into the core standard to promote stability and avoid introducing highly experimental elements that could complicate adoption.[7] In scope, C++23 offers a smaller yet more focused evolution compared to the transformative changes in C++20, with an emphasis on library enhancements for greater productivity and refinements to language precision for safer and more expressive code.[6] Its impact on the C++ ecosystem includes enabling improved support for modern hardware via optimized data structures and multidimensional views, facilitating safer code through refined error handling, and diminishing dependence on traditional headers through mature module support.[6] These advancements collectively streamline development workflows and enhance performance in contemporary applications.Modern "Hello, World!" Example
A quintessential demonstration of C++23's advancements is the simplified "Hello, World!" program, which leverages the new standard library module and formatted output functions to eliminate traditional header inclusions and stream manipulations.[8]import std;
int main() {
std::println("Hello, world!");
}
import std;
int main() {
std::println("Hello, world!");
}
import std; brings in the entire standard library as a module, replacing the conventional #include directives and providing faster compilation times with better encapsulation by avoiding global namespace pollution from macros.[8] Modules support for the standard library, including std, is detailed in the dedicated section on Modules and Import Support. Meanwhile, std::println from the <print> header outputs the formatted string to stdout followed by a newline, streamlining I/O operations that previously required std::cout, insertion operators, and explicit flushing via std::endl.
To compile this program, a C++23-compliant compiler is required, such as GCC 13 or later invoked with the -std=c++23 flag (e.g., g++ -std=c++23 hello.cpp -o hello), though full module support may vary by implementation and could necessitate additional build system configurations like CMake for prebuilt standard modules. As of 2025, GCC 15 or later offers full support for modules and std::println.[4]
For comparison, the C++20 equivalent relies on headers and streams, resulting in more verbose code:
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
}
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
}
Standardization Process
Development Timeline
Following the finalization of C++20 at the WG21 meeting in Prague from February 10 to 15, 2020, the committee shifted focus to C++23, adopting a development plan outlined in paper P0592R4 that emphasized completing foundational work on modules—initially introduced in C++20—and enhancing ranges support to improve library usability.[10] The COVID-19 pandemic disrupted in-person gatherings, leading to the cancellation of the planned June 2020 meeting in Varna, Bulgaria, and a transition to virtual meetings throughout 2020 and 2021.[11] During this period, key proposals advanced significantly, including explicit object parameters (P0849R8) for simplifying member function calls and std::expected (P0323R15) for error-handling utilities, both of which progressed toward adoption in C++23 through reflector discussions and virtual plenaries, such as the November 9, 2020, Zoom meeting.[12] In 2022, the committee continued with virtual sessions early in the year, including the February virtual meeting, before resuming hybrid in-person formats with the November 7-12 meeting in Kona, Hawaii, hosted by the Standard C++ Foundation.[13][14] This period approached feature freeze, achieved at the July 25 virtual plenary, where core features like coroutines library support (including std::generator) and multidimensional arrays via std::mdspan were finalized for inclusion.[15][16] The February 6-11, 2023, meeting in Issaquah, Washington, marked the completion of C++23's technical specifications, leading to the final committee draft N4950 dated May 10, 2023.[12][17] Subsequent meetings in Varna, Bulgaria (June 12-17), and Kona, Hawaii (November 6-11), handled defect reports, wording refinements, and ballot preparations, leading to national body ratification.[12][17] In 2024, the International Organization for Standardization (ISO) published C++23 as ISO/IEC 14882:2024 on October 1, formalizing the standard after editorial review.[1] Post-publication, major compilers integrated C++23 support progressively; as of November 2025, GCC 15, Clang 19, and Visual Studio 2022 version 17.14 offer substantial to near-complete implementation, enabling widespread adoption.[18][19][20]Key Milestones and Meetings
The ISO/IEC JTC1/SC22/WG21 working group, known as the C++ standards committee, is responsible for evolving the C++ programming language standard through a collaborative process involving national body representatives and individual experts.[21] This group reviews technical papers submitted by members, conducts discussions in working group sessions during triannual meetings, and uses polls to gauge consensus on proposed changes before forwarding recommendations for inclusion in the working draft.[22] Key decisions shaping C++23 included several pivotal votes at WG21 meetings. At the February 2023 meeting in Issaquah, Washington, USA, the committee approved the final draft of the C++23 standard by unanimous consent after resolving all national body comments, marking the technical completion of the specification.[23] Earlier, in June 2022 at the St. Louis meeting, WG21 polled in favor of including P2465R3, which introduced standard library modules such asstd and std.compat to facilitate modular imports of the C++ library.[24] However, the Contracts Technical Specification was rejected for integration into C++23 due to insufficient consensus stemming from concerns over semantic complexity and implementation challenges.[23]
C++23 incorporated features from several Technical Specifications (TS) into the core standard, promoting stability and adoption. The Library Fundamentals V3 TS contributed components like std::expected for error handling and std::mdspan for multidimensional array views.[25] Enhancements from the Ranges TS, including additional views and algorithms, were fully integrated to extend C++20's ranges foundation.[26] The Coroutines TS provided the basis for std::generator, enabling lazy sequence generation in standard library coroutines.[27] These integrations were approved via polls in LEWG (Library Evolution Working Group) sessions leading up to the feature freeze in July 2022.[16]
Following the February 2023 feature freeze, WG21 addressed post-freeze defects through targeted resolutions. The Core Working Group (CWG) and Library Working Group (LWG) reviewed and fixed ambiguities in ranges, such as iterator invalidation rules, and attributes, including clarification of [[likely]] and [[unlikely]] semantics, via immediate-issue polls at the Issaquah meeting.[28]
WG21's evolution policy employs a decoupled model, where experimental features are first previewed in separate Technical Specifications to allow real-world testing and refinement without delaying the main standard's publication cycle. This approach enabled the progressive maturation of ranges, coroutines, and library fundamentals from TS to full standardization in C++23.
Language Features
Core Syntax Enhancements
C++23 introduces core syntax enhancements that streamline member function definitions, operator overloads, literal expressions, and namespace declarations, thereby increasing code expressiveness while minimizing redundancy in common programming patterns. A key feature is deducing this (P0847R8), which permits non-static member functions to deduce their return type based on the cv- and ref-qualifiers of the implicit this parameter, eliminating the need for separate overloads to handle lvalue and rvalue contexts. This enables a unified implementation for operations like assignment or chaining, where the return type adjusts automatically—for instance, returning a reference for lvalues and an rvalue reference for rvalues. Consider this example in a class definition:struct Widget {
auto operator+=(const auto& rhs) { /* implementation */ return *this; }
};
struct Widget {
auto operator+=(const auto& rhs) { /* implementation */ return *this; }
};
struct Foo {
void print(this Foo& self) { /* use self */ }
};
struct Foo {
void print(this Foo& self) { /* use self */ }
};
operator[] to accept multiple arguments, supporting direct multi-index access for multidimensional data structures without relying on deprecated comma expressions or nested calls. This syntactic upgrade is particularly beneficial for user-defined types representing arrays or views, allowing overloads with fixed or variadic parameters that include the explicit object for consistency. An illustrative declaration is:
struct Matrix {
double& operator[](this Matrix&& self, size_t row, size_t col);
};
struct Matrix {
double& operator[](this Matrix&& self, size_t row, size_t col);
};
matrix[1, 2] = 3.14; becomes idiomatic, promoting readability in numerical and scientific computing while integrating with library features like multidimensional views.[29]
To mitigate common type promotion issues with size-related constants, C++23 adds literal suffixes for std::size_t and its signed counterpart (std::ptrdiff_t or equivalent), as specified in P0330R8. The 'uz' (or 'UZ') suffix denotes an unsigned size_t literal, while 'z' (or 'Z') indicates the signed variant, preventing implicit conversions and associated warnings. For instance:
std::vector<int> vec(42uz);
std::vector<int> vec(42uz);
size_t may differ from built-in unsigned integers.[30]
C++23 also clarifies and reinforces support for nested inline namespaces within enclosing inline namespaces, enhancing library evolution through transitive visibility for versioned APIs. Inline declarations propagate through nesting levels, allowing unqualified access to inner members as if declared in the outer scope, which simplifies maintaining backward-compatible hierarchies without altering lookup rules. This builds on C++11 foundations to facilitate cleaner, scalable namespace organization in large projects.
Compile-Time Improvements
C++23 introduces several enhancements to compile-time evaluation, enabling more sophisticated computations during compilation while maintaining runtime efficiency. These improvements build on prior standards by expanding the scope of constant expressions, allowing developers to perform operations that were previously deferred to runtime. Key advancements include conditional branching based on evaluation context, mechanisms for ensuring immediate evaluation in functions, and extended support for standard library containers in constant expressions. One significant addition is theif consteval construct, which permits conditional compilation depending on whether a function is invoked in a constant evaluation context. This feature addresses limitations in distinguishing between compile-time and runtime invocations within constexpr and consteval functions, reducing reliance on the std::is_constant_evaluated() function and enabling more flexible code that behaves differently at compile time versus runtime. For example, the following code snippet demonstrates its use:
consteval int compute(int x) {
if consteval {
return x * 2; // Optimized for [compile-time](/page/Compile_time)
} else {
return x * 3; // Fallback for runtime
}
}
consteval int compute(int x) {
if consteval {
return x * 2; // Optimized for [compile-time](/page/Compile_time)
} else {
return x * 3; // Fallback for runtime
}
}
auto(x) initialization. This syntax creates a prvalue from x as if it were passed by value to a function, ensuring the expression is suitable for constant evaluation without odr-use (one definition rule) violations. It is particularly useful in lambda expressions or function definitions where compile-time guarantees are needed. Consider this example for a compile-time square function:
constexpr auto square = [](auto(x)) { return x * x; };
static_assert(square(5) == 25);
constexpr auto square = [](auto(x)) { return x * x; };
static_assert(square(5) == 25);
std::vector and std::string in constant expressions under the transient allocation model, where any simulated dynamic allocation must be deallocated within the same constant evaluation. This enables temporary use of these containers for compile-time computations, such as generating data, but they cannot persist beyond the evaluation (persistent allocation is proposed for future standards). For instance, a constexpr function can use a vector internally to compute a value:
constexpr int fib(int n) {
std::vector<int> v{0, 1};
for (int i = 2; i < n; ++i) {
v.push_back(v[i-1] + v[i-2]);
}
return v.back();
}
static_assert(fib(6) == 8);
constexpr int fib(int n) {
std::vector<int> v{0, 1};
for (int i = 2; i < n; ++i) {
v.push_back(v[i-1] + v[i-2]);
}
return v.back();
}
static_assert(fib(6) == 8);
std::string for compile-time string operations like concatenation.[33]
To enhance portability in internationalized code, C++23 mandates UTF-8 as the portable source file encoding, ensuring compilers accept UTF-8 input by default. This change standardizes handling of Unicode characters in source code, reducing encoding-related portability issues across platforms and compilers. It affects literal encoding and execution character sets, making it easier to write code with non-ASCII identifiers and strings without vendor-specific flags.[34]
Additionally, C++23 allows static operator[] as a member function, enabling array-like subscript access in constant expressions without requiring an object instance or triggering odr-use. This is valuable for stateless classes or constexpr contexts where traditional non-static operators would necessitate unnecessary object creation. For example:
struct ArrayView {
static constexpr int operator[](size_t i) { return data[i]; }
static constexpr int data[5] = {1, 2, 3, 4, 5};
};
static_assert(ArrayView::operator[](2) == 3);
struct ArrayView {
static constexpr int operator[](size_t i) { return data[i]; }
static constexpr int data[5] = {1, 2, 3, 4, 5};
};
static_assert(ArrayView::operator[](2) == 3);
Attribute and Diagnostic Features
C++23 introduces several attributes and diagnostic enhancements designed to provide programmers with finer control over compiler optimizations and improved error reporting during compilation. These features build on prior standards by standardizing optimization hints and refining how diagnostics are generated and displayed, particularly in template contexts. The [[assume]] attribute, for instance, enables developers to inform the compiler of assumed conditions without runtime evaluation, facilitating aggressive optimizations while introducing undefined behavior if the assumption proves false. Similarly, the [[likely]] and [[unlikely]] attributes, now applicable in broader contexts, offer branch prediction hints to guide code generation for performance-critical paths.[35][36] The [[assume]] attribute allows a programmer to assert that a given constant expression evaluates to true at a specific point in the code, enabling the compiler to optimize accordingly without verifying the condition at runtime. For example, consider the following code snippet where the assumption optimizes away unnecessary checks:int process_positive(int x) {
[[assume(x > 0)]];
return x * 2; // Compiler can assume x > 0, potentially simplifying operations
}
int process_positive(int x) {
[[assume(x > 0)]];
return x * 2; // Compiler can assume x > 0, potentially simplifying operations
}
void handle_request(bool error) {
if ([[unlikely]](error)) {
// Rare error path: compiler may place this code out-of-line
log_error();
return;
}
// Common success path
process_data();
}
void handle_request(bool error) {
if ([[unlikely]](error)) {
// Rare error path: compiler may place this code out-of-line
log_error();
return;
}
// Common success path
process_data();
}
template<typename T>
void check_type() {
static_assert(sizeof(T) == 4, "T must be a 32-bit type"); // Now reliably emits in dependent contexts
}
template<typename T>
void check_type() {
static_assert(sizeof(T) == 4, "T must be a 32-bit type"); // Now reliably emits in dependent contexts
}
Library Features
Modules and Import Support
C++23 advances the modules feature originally introduced in C++20 by standardizing support for the entire standard library as a module, enabling more efficient and encapsulated code organization without relying on traditional header inclusions. This integration resolves lingering issues from the earlier Modules Technical Specification, such as inconsistent compiler behaviors and limited library exposure, providing a production-ready mechanism for modular programming. Modules promote faster build times by compiling interface information once and reusing it, while reducing macro-related side effects and name collisions inherent in header files. A major addition in C++23 is the named modulestd, accessible via import std;, which exposes all declarations within namespace std from C++ standard headers (e.g., std::vector from <vector>) and C wrapper headers (e.g., std::fopen from <cstdio>), along with global operators like ::operator new from <new>. This design excludes global namespace equivalents to prevent namespace pollution, offering a clean import path for new code. For legacy compatibility, the std.compat module, imported as import std.compat;, includes everything from std plus the corresponding global namespace functions (e.g., ::fopen), easing the transition for codebases that rely on C-style globals. These modules are defined in the C++23 standard to balance adoption and modernity, with minimal impact on compilation throughput due to modular optimizations.
Module partitions enhance scalability by allowing a single named module to be divided into a primary interface unit and multiple partition interface units, where partitions can be internal (non-exported) for private implementation or interface partitions for shared components. This structure supports better encapsulation in large projects by isolating details within partitions that are not visible outside the module. The global module fragment, delimited by module; before the module declaration, permits inclusions of headers (e.g., system headers like <windows.h>) that remain visible to importers without being exported, facilitating compatibility with non-modular code. Complementing this, the private module fragment—declared with module :private; and restricted to the primary module interface unit—hides internal declarations and definitions from importers, further strengthening encapsulation by preventing unintended exposure of implementation specifics.
Header units in C++23 provide a bridge for existing headers, allowing them to be imported directly as import <header-name>; without full rewriting into module syntax. This treats the header's content as a self-contained module unit, preserving macro definitions and inline functions while benefiting from module caching for repeated uses. C++23 refines header unit compatibility, improving integration with named modules and reducing parsing overhead in mixed header-module environments.
Export mechanisms in C++23 offer refined handling of templates within modules, permitting template declarations and definitions to be exported via the module interface without requiring full instantiation in every importing unit, unlike traditional headers where definitions must often be visible at the point of use. This enables more efficient template distribution, as the module's binary interface includes necessary template information for instantiation on demand, addressing prior limitations in the Modules TS.
Ranges and Algorithms
C++23 introduces several enhancements to the Ranges library, building on the foundation laid in C++20 by standardizing additional views and algorithms from the Ranges Technical Specification (TS) while adding new functionality to improve composability and expressiveness in data processing. These changes emphasize lazy evaluation, better support for heterogeneous data, and efficient reduction operations, enabling more idiomatic and performant code for iterating and transforming sequences without unnecessary copies. The updates follow the prioritization outlined in the C++23 Ranges plan, which categorizes features into tiers based on maturity and utility, ensuring that core views and algorithms are fully integrated into the standard library.[37] One key addition is the family of fold algorithms, which provide flexible ways to reduce a range to a single value using a binary operation. The primary functions arestd::ranges::fold_left and std::ranges::fold_right, which perform left-associative and right-associative folds, respectively, starting from an initial value. For example, std::ranges::fold_left applies the operation cumulatively from left to right, equivalent to the expression init op x1 op x2 op ... op xn, and is particularly useful for operations like summing or concatenating elements where order matters. These algorithms support both forwarding and input ranges, with overloads that deduce the initial value from the first element if not provided, and they reside in <algorithm> to align with general-purpose reductions rather than numeric-specific ones. Additionally, std::ranges::fold_left_with_iter allows specifying a starting iterator for partial folds, enhancing control over the reduction process. This design addresses limitations in prior standards, such as the lack of guaranteed left-to-right evaluation in std::reduce, and promotes safer, more predictable computations in parallel contexts when combined with execution policies in future standards.[38]
The std::views::join view is another significant enhancement, allowing the flattening of a nested range of ranges into a single flat sequence. It takes a view of ranges—such as a vector of vectors—and produces a concatenated view where inner ranges are seamlessly iterated as if they were a continuous sequence, preserving the input range's category (e.g., input or random access). For instance, applying views::join to a range of strings yields a single stream of characters, useful for text processing or aggregating subcollections without materialization. This view requires the outer range to model input_range and each inner range to model input_range as well, with support for prvalue non-views through relaxed constraints to avoid unnecessary temporaries. An extension, std::views::join_with, inserts a delimiter between joined elements, such as commas in CSV-like data, further aiding serialization tasks. These features stem from efforts to make nested data handling more composable, directly addressing common patterns in functional-style programming.[39][40]
Improvements to the zip view in C++23 enhance its utility for combining multiple heterogeneous ranges into tuples, supporting variadic numbers of input views with better type deduction and proxy iterator integration. The std::views::zip adaptor produces a view of tuple-like elements, where each tuple holds the i-th element from each zipped range, stopping at the shortest range's end to prevent out-of-bounds access. Unlike earlier experimental versions, the C++23 implementation uses std::tuple for more than two ranges and std::pair for exactly two, ensuring compatibility with structured bindings and generic code; it also supports heterogeneous types by allowing arbitrary view arguments without common reference type requirements. This enables scenarios like parallel iteration over disparate containers, such as zipping a vector of keys with a map of values for dictionary operations. The design includes optimizations for proxy references in common views like transform, making it efficient for lazy pipelines.[41]
New range-based algorithms expand search capabilities, including std::ranges::find_last and its variants (find_last_if, find_last_if_not), which locate the last occurrence of a value or predicate-satisfying element in a range. These return an iterator to the found position or std::ranges::dangling if none exists, supporting bidirectional and random-access ranges for efficiency. For example, std::ranges::find_last_if can identify the last even number in a sequence, complementing forward-only searches. Similarly, std::ranges::adjacent_find detects the first pair of consecutive elements satisfying a binary predicate, rangified from the legacy version to work with views and return a subrange or iterator pair for easier chaining. These additions fill gaps in backward and pairwise searching, promoting more expressive code without manual reverse iteration.[42]
C++23 fully standardizes several features from the Ranges TS, notably std::views::zip and std::views::enumerate, integrating them as Tier 1 views for immediate usability. The enumerate view pairs each element with its zero-based index in a tuple, facilitating indexed operations like mapping with position awareness, and models the same range category as its underlying view. This standardization ensures these adaptors are lightweight, composable, and free of the TS's experimental constraints, allowing seamless use in standard containers and algorithms.[43][37]
Utilities and Formatting
C++23 introduces several enhancements to the standard library's utilities, focusing on improved error handling, formatted output, associative containers, and time zone management. These additions aim to provide more robust, type-safe, and efficient tools for common programming tasks, building on prior standards while addressing longstanding needs in text processing and data organization. One key addition isstd::print and std::println, which offer type-safe formatted output directly to streams like stdout or stderr, avoiding the overhead of intermediate string construction required by std::format. These functions use a printf-like syntax with compile-time checks for format specifiers, ensuring arguments match the placeholders. For instance, the code std::print("Value: {:d}\n", 42); outputs "Value: 42" followed by a newline, while std::println automatically appends a newline. This design supports Unicode output portably and integrates with the <print> header, providing a convenient alternative to std::cout for simple logging and debugging.
To improve error handling, C++23 standardizes std::expected<T, E>, a monadic type that encapsulates either a successful value of type T or an error of type E, akin to optional results in other languages. It supports operations like value_or to retrieve the value with a default on error, and or_else for chaining error recovery, promoting functional-style error propagation without exceptions. Constructors allow in-place construction of the value or error, and it integrates with concepts for generic usage. For example, a function might return std::expected<int, std::error_code>, enabling callers to handle success or failure explicitly. This feature addresses the need for lightweight error handling in performance-critical code.[44]
Format string handling receives refinements through enhanced support in std::format, incorporating concepts for compile-time validation of user-defined formatters and better integration with standard types. Proposals extend formatting for ranges and tuples with customizable debug output. These changes leverage C++20's std::format foundation, adding specializations for library types like std::span and improving locale-aware formatting without altering core syntax.
New associative containers std::flat_map and std::flat_set provide sorted, unique key-based storage using a contiguous underlying vector, offering faster iteration and smaller memory footprints compared to tree-based std::map and std::set for small-to-medium datasets. Elements are kept sorted by key, with insertion maintaining order via binary search, achieving O(log n) lookups and O(n log n) construction. Unlike traditional maps, they support reserving capacity to avoid reallocations, and provide views like keys() for key-only access. An example usage is std::flat_map<std::string, int> m; m.emplace("key", 42);, ideal for cache-friendly scenarios where iteration speed matters more than frequent insertions. Variants std::flat_multimap and std::flat_multiset allow duplicates.
Time zone support in <chrono> is bolstered by std::chrono::zoned_time, which pairs a time_point with a time_zone for unambiguous local time representation, including automatic handling of ambiguities like daylight saving transitions. C++23 clarifies locale-dependent formatting for zoned times. This enables code like auto zt = zoned_time{current_zone(), sys_time{std::chrono::system_clock::now()}}; std::print("{:%F %T %Z}", zt); to output locale-aware dates with zone abbreviations, enhancing cross-platform date-time applications. Brief integration with ranges allows formatting sequences of times, as detailed elsewhere.
Multidimensional Arrays and Views
C++23 introducesstd::mdspan, a non-owning multidimensional view that provides a multi-index abstraction over a contiguous sequence of objects in memory, enabling efficient representation of arrays with multiple dimensions without owning the underlying data.[45] This class template is defined in the <mdspan> header and interprets the memory as a domain defined by extents in each dimension, facilitating portable and performant access patterns in multidimensional data structures.[45]
The extents of an mdspan can be specified at compile time using std::extents, such as std::mdspan<int, std::extents<std::size_t, 3, 4>> view(arr);, which creates a view over a contiguous array arr representing a 3-by-4 matrix.[46] Dynamic extents are supported through the std::dynamic_extent sentinel value, allowing runtime specification of sizes; for example, std::mdspan<float, std::dynamic_extent, std::dynamic_extent> dynamic_view(data, rows, cols); constructs a view with dimensions provided at runtime.[46] Extents can mix static and dynamic specifications, such as std::mdspan<float, 20, std::dynamic_extent> mixed_view(data, num_cols);, where the first dimension is fixed at 20 while the second varies.
Layout policies in std::mdspan control the mapping of multidimensional indices to linear memory offsets, with std::layout_right providing row-major order (last index varies fastest, as in C-style arrays) and std::layout_left providing column-major order (first index varies fastest, as in Fortran).[45] These policies are specified as template parameters, e.g., std::mdspan<int, std::extents<std::size_t, 3, 4>, std::layout_right> row_major_view(arr);, ensuring compatibility with diverse hardware and numerical libraries.[45]
Integration with C++23's multidimensional subscript operator allows intuitive access like view[i][j], where the language feature (detailed in Core Syntax Enhancements) enables operator[] to accept multiple arguments, returning nested views for subsequent indexing.[47] This syntax supports zero or more arguments in operator[] overloads, aligning mdspan access with familiar array notations while preserving type safety and efficiency.[47]
In high-performance computing (HPC) and scientific computing, std::mdspan addresses the need for lightweight, non-owning views over large datasets, avoiding the overhead of full array copies and enabling performance portability across accelerators and CPUs without vendor-specific extensions.[46] It facilitates kernel algorithms in domains like linear algebra and simulations by providing a standard interface for multidimensional indexing, reducing boilerplate and improving interoperability with libraries such as those in the Kokkos ecosystem.[46]
Other Library Additions
C++23 introduces the<stacktrace> header as part of the diagnostics library, providing facilities to capture, store, and output call stack information at runtime.[48] The core class std::stacktrace represents a sequence of stack frames, obtained via std::stacktrace::current() to capture the current call stack or constructed from an exception object for error handling.[48] Each frame is described by std::stacktrace_entry, which includes the source file name, function name, and address, enabling detailed debugging output through operator overloading for streams like std::cout.[48]
To support lazy evaluation in ranges using coroutines—building on the coroutine syntax introduced in C++20—std::generator is added to the standard library.[49] This class template generates a sequence of values on demand by suspending and resuming the coroutine returned from a generator function, integrating seamlessly with range-based algorithms via co_yield statements.[49] For example, a generator can produce elements of type T or optionally std::optional<T> to signal completion, avoiding the need for custom coroutine types in common iterable scenarios.[50]
The <bit> header gains std::byteswap, a constexpr function that reverses the byte order of an integral value, aiding endianness conversions in network protocols and serialization without platform-specific code.[51] It participates in overload resolution only for integral types and produces the same type as its argument, ensuring type safety and compile-time evaluation where possible.[51]
Complementing this, std::ranges::views::as_rvalue (also known as std::views::as_rvalue) provides a range view adaptor that treats each element as an rvalue reference, equivalent to wrapping the range's iterators in std::move_iterator, to facilitate moving from containers in algorithms without explicit wrapping.[52]
For C compatibility and low-level string conversion, std::to_chars for integral types is made constexpr in C++23, enabling allocation-free, compile-time conversion of integers to character buffers in a specified base (decimal, hexadecimal, or octal).[53] This update, per proposal P2291R3, ensures round-trip guarantees and locale independence, useful for embedded systems or performance-critical parsing without dynamic memory use.[54]
Deprecations and Removals
Removed Language Features
In C++23, the ISO/IEC 14882 standard removed support for garbage collection interfaces that had been part of the language since C++11, as these features were never implemented in major standard library implementations and provided limited practical value. Specifically, the functionsstd::declare_reachable, std::undeclare_reachable, std::declare_no_pointers, std::undeclare_no_pointers, and std::get_pointer_safety from the <gc> header were eliminated, along with the std::pointer_safety enumeration and the __STDCPP_STRICT_POINTER_SAFETY__ macro. Additionally, core language wording related to strict pointer safety, which aimed to support conservative garbage collectors by guaranteeing pointer validity, was excised. This removal stemmed from the absence of any known compiler or library support for strict pointer safety over the past decade, with all major implementations defaulting to relaxed mode, rendering the feature obsolete and unhelpful for real-world garbage collection in virtual machines or custom allocators.[55]
Another language cleanup in C++23 involved the elimination of non-encodable wide character literals and multicharacter wide character literals, which were previously allowed but led to inconsistent behavior across implementations due to varying execution character set assumptions. Under the new rules, attempts to form such literals, like L'non-encodable-char' where the character cannot be represented in the execution wide character set, or L'abc' with multiple characters, now result in ill-formed code, requiring a diagnostic from the compiler. This change simplifies the grammar and reduces portability issues without impacting common use cases, as narrow character literals or user-defined literals serve equivalent purposes.[56]
C++23 also removed support for concatenating mixed wide string literals, such as u"q" U"p", which previously allowed inconsistent combinations of encoding prefixes (e.g., u8, u, U, L). These are now ill-formed, promoting consistent encoding practices and aligning with enhanced Unicode support in the standard. This cleanup addresses ambiguities in literal formation without affecting typical string usage.[57]
These removals contribute to streamlining the C++ core language by excising unused or contradictory provisions accumulated from prior standards, particularly those in Annex D (compatibility) that no longer align with modern hardware and implementation realities. For instance, certain legacy rules conflicting with cache-coherent multiprocessor systems were pruned to focus the specification on practical, widely-adopted behaviors, thereby reducing complexity and specification bloat without breaking existing codebases. The overall rationale emphasizes enhancing maintainability and clarity for developers and implementers, prioritizing features with demonstrated utility over vestigial elements.[58]
Deprecated Library Components
In C++23, the standard library deprecates several legacy components to promote safer, more efficient alternatives, continuing a process started in previous standards. The<codecvt> header, introduced in C++11 to support conversions between different character encodings via facets like std::codecvt_utf8, remains deprecated as established in C++17. This deprecation stems from the header's underspecification, absence of robust error handling, and potential security vulnerabilities in conversion operations. Although not removed in C++23, it is slated for elimination in C++26, with implementers advised to maintain backward compatibility in the interim. Developers are encouraged to migrate to third-party libraries such as ICU for comprehensive Unicode handling or leverage emerging standard facilities like std::text_encoding for basic encoding needs.[59]
C++23 newly deprecates std::aligned_storage and std::aligned_union from the <type_traits> header, which provided types for aligned storage allocation but are redundant with the more flexible std::align algorithm and modern alignment specifications introduced in C++11. These deprecations encourage use of aligned allocation functions and structured bindings for similar purposes, reducing reliance on utility classes that overlap with core language features.[60]
Additionally, the member std::numeric_limits::has_denorm is deprecated in C++23, as its behavior was underspecified for certain floating-point models and rarely used in practice. Developers should instead query denormalization support via std::numeric_limits::tininess_before or implementation-specific checks, aligning with updates to floating-point semantics in the standard.[61]
For migration from these deprecated components, C++23 emphasizes modern utilities like std::format for string and I/O operations that once relied on legacy encoding or shuffling patterns, offering type-safe and locale-aware formatting without the pitfalls of older facilities. Comprehensive tooling support in compilers flags these deprecations, facilitating gradual upgrades in large codebases.[58]
Compiler and Tooling Support
Major Compiler Implementations
GCC provides robust support for C++23, with core language features largely implemented starting in GCC 14, released in May 2024. Substantial completion, including advanced modules and multidimensional array support viastd::mdspan, arrived in GCC 15.1 (April 2025), with further enhancements in GCC 15.2 (August 2025).[62] This version enhances experimental modules with built-in std and std.compat modules, alongside library additions like std::flat_map and std::flat_set.[63]
Clang, part of the LLVM project, began progressive implementation of C++23 features from Clang 13 in 2021, reaching substantial coverage by Clang 16 in 2023.[19] Full support, enabling the -std=c++23 flag for comprehensive compliance, was achieved in Clang 18, released in September 2024. This includes modules import syntax and standard library integrations, with ongoing refinements in subsequent point releases.[19]
Microsoft Visual C++ (MSVC) introduced C++23 support in Visual Studio 2022 version 17.10, released in May 2024, via the /std:c++23 compiler flag.[20] By mid-2025, in version 17.14 (May 2025), key features such as modules and the <print> header with std::print and std::println became fully available, along with support for new lambda attributes, if consteval, and static operators, aligning with ISO conformance goals.[64]
Other compilers exhibit varying degrees of adoption. Intel oneAPI DPC++/C++ Compiler version 2025.0, leveraging the Clang 19 frontend, provides full C++23 support across host and device code.[65] NVIDIA HPC SDK compilers, formerly PGI, offer complete C++23 compatibility in release 25.9 (September 2025), including GPU-accelerated standard library elements.[66] EDG-based frontends, used in tools like MSVC's IntelliSense, deliver partial C++23 implementation, covering core language but lagging on modules.[67]
To invoke C++23 mode, compilers typically require explicit flags: g++ -std=c++23 for GCC, clang++ -std=c++23 for Clang, and cl /std:c++23 for MSVC. These enable the standard's features while maintaining backward compatibility with prior modes.[20]
