C++23, formally ISO/IEC 14882:2024 (the seventh edition), is the version of the C++ programming language standard published in October 2024. It follows C++20. N4950 is the final WG21 working draft for C++23, and WG21 completed the technical work on the revision at its meeting in February 2023. The successor revision, commonly referred to as C++26, is being developed as ISO/IEC DIS 14882, which ISO identifies as the next version intended to replace ISO/IEC 14882:2024.
Compiler support for C++23 varies by compiler version, language feature, and standard-library component. Clang lists C++23 mode as partial, while GCC describes its implementation as experimental; Microsoft publishes feature-by-feature conformance information for Visual C++.
Features
Changes accepted into C++23 include the following language and standard-library features. A feature-by-feature summary is also maintained by cppreference.
multidimensional subscript operator; this operator may be defined with any number of parameters (or even be variadic), allowing for defining a[i,j,k]=x; instead of a[i][j][k]=x;
static operator() and operator[] functions, and static lambdas
simplifying implicit move
auto(x) and auto{x}
new preprocessor directives:
#elifdef and #elifndef
#warning
extending the lifetime of temporaries within the range-initializer of a range-based for loop to the lifetime of the loop
new standard attribute [[assume(expression)]]
class template argument deduction from inherited constructors
labels at the end of compound statements
alias declarations in init-statements
integer-literal suffixes z for the corresponding signed integer type and uz or zu for std::size_t (for example, 0z and 15zu)
extended floating-point types with literals (conditionally supported)
non-literal variables, labels, and gotos in constexpr functions
allowing static and thread_local variables that are usable in constant expressions in constexpr functions
relaxing restrictions on constexpr functions, including permitting a function to be declared constexpr even if no invocation satisfies the requirements for a core constant expression
narrowing contextual conversions to bool in static_assert and ifconstexpr
trimming whitespaces before line splicing
requiring declaration-order layout for non-static data members, subject to the rules for potentially overlapping subobjects
delimited escape sequences
named universal character escapes
text encoding changes:
support for UTF-8 as a portable source file encoding
made std::tuple compatible with other tuple-like objects
std::basic_common_reference specialization for std::reference_wrapper yielding reference types
adding default template arguments for std::pair<T, U>'s forwarding constructor
Compile-time Support
constexpr support for:
std::type_info::operator==
std::bitset
std::unique_ptr
for some <cmath> functions
for integral overloads of std::to_chars and std::from_chars
metaprogramming utilities:
type traits std::is_scoped_enum, std::is_implicit_lifetime, std::reference_constructs_from_temporary, and std::reference_converts_from_temporary.
adding move-only types support for comparison concepts
Iterators, Ranges, and Algorithm Support
range conversion utility std::ranges::to
new constrained ranges algorithms:
std::ranges::starts_with
std::ranges::ends_with
std::ranges::contains
std::ranges::contains_subrange
std::ranges::find_last and other variants
rangified versions of iota, shift_left, and shift_right
range fold algorithms
new std::ranges::range_adaptor_closure, a helper for defining user-defined range adaptor closures
new range adaptors:
the std::views::zip family, including zip_transform
the std::views::adjacent family, including adjacent_transform
std::views::join_with
std::views::slide
std::views::chunk
std::views::chunk_by
std::views::as_rvalue
std::views::as_const
std::views::repeat
std::views::stride
std::views::cartesian_product
std::views::enumerate
rectifying constant iterators, sentinels, and ranges, that is, std::ranges::cbegin and other similar utilities returning constant iterators should be fully guaranteed even for shallow-const views (such as std::span)
ranges iterators as inputs to non-ranges algorithms
relaxing range adaptors to allow for move only types
making multi-param constructors of some views explicit
Memory Management Support
std::out_ptr and std::inout_ptr for C interoperability
std::allocator_traits<Alloc>::allocate_at_least and std::allocator<T>::allocate_at_least
explicit lifetime management function std::start_lifetime_as for implicit-lifetime types
disallowing user specialization of std::allocator_traits
String and Text Processing Support
new member functions and changes in string types:
std::basic_string_view::contains and std::basic_string::contains
disabling construction from nullptr for std::basic_string and std::basic_string_view
explicit range constructor for std::basic_string_view
std::basic_string::resize_and_overwrite
rvalue-qualified overload of std::basic_string::substr, which can reuse storage when called on an rvalue string
formatting ranges and tuples, escaped presentation of characters and strings, and formatting of std::thread::id and stacktraces.
Diagnostic Support
stacktrace library, header <stacktrace> and type std::stacktrace
I/O Support
formatted output functions std::print and std::println from new header <print>
spanstream library (std::span-based string stream) from new header <spanstream>
constructability and assignability of containers from other compatible ranges
flat associative-container adaptors: std::flat_map, std::flat_multimap, std::flat_set and std::flat_multiset
non-deduction context for allocators in container deduction guides
heterogeneous erasure overloads for associative containers
allowing iterator pair construction in stack and queue
requiring std::span and std::basic_string_view to be trivially copyable
C-Compatibility Support
new header <stdatomic.h>
Language defect reports
C++ identifier syntax using Unicode Standard Annex 31
allowing duplicate attributes
changing scope of lambda trailing return type
making the effects of rewritten comparison candidates less disruptive to existing code
undeprecating volatile compound assignments
fixing some compatibility and portability issues involving char8_t and UTF-8 string literals
relaxing requirements on wchar_t to match existing practices
relaxing restrictions on using certain pointers and references of unknown origin in constant expressions
introducing immediate-escalating functions, which can become immediate functions under specified conditions
allowing static_assert(false) in uninstantiated template contexts
Library defect reports
changes in ranges library:
conditionally borrowed ranges
repairing input range adaptors and std::counted_iterator
relaxing the constraint on std::ranges::join_view
renamed std::ranges::split_view to std::ranges::lazy_split_view and new split_view
removed std::default_initializable constraint from concept std::ranges::view
view with ownership and new std::ranges::owning_view
fixed std::ranges::istream_view
changes in text formatting library:
std::basic_format_string
compile-time format string checks
reducing binary code size of std::format_to
fixing locale handling in chrono formatters
improving width estimation and fill character allowances of std::format
use of forwarding references in format arguments to allow non-const-formattable types
fully constexprstd::variant and std::optional
supporting types derived from std::variant in std::visit
Removed features and deprecation
Removed features:
Removed the language and standard-library provisions for garbage-collection support and reachability-based leak detection, including the strict pointer-safety interface. This removes those facilities from the C++ standard but does not prevent C++ programs from using separate garbage-collection libraries.
Mixed wide-string literal concatenation.
Non-encodable wide character literals and multicharacter wide character literals.
Deprecated features:
std::aligned_storage and std::aligned_union
std::float_denorm_style, std::numeric_limits<T>::has_denorm and std::numeric_limits<T>::has_denorm_loss
Reverted deprecations:
The use of the comma operator in subscript expressions is no longer deprecated. C++23 also changes the rules for overloaded operator[] so that it can take multiple parameters.
The corresponding C-compatibility headers with .h suffixes are no longer deprecated, although their use is discouraged in C++-only code where C interoperability is not needed.
Related technical specification
The Concurrency Technical Specification, second edition, was published separately as ISO/IEC TS 9922:2024. It specifies an interface through which C++ programs can invoke algorithms with concurrent execution; it is a separate technical specification, not part of ISO/IEC 14882:2024.
Compiler support
Support for C++23 varies by compiler version and by language and standard-library feature; enabling a C++23 language mode does not imply complete implementation of the standard.
Clang provides the -std=c++23 mode, but its status page lists C++23 support as partial.
GCC provides the -std=c++23 mode, as well as -std=gnu++23 for GNU extensions. Its status page describes its C++23 implementation as experimental and lists support feature by feature.
Microsoft Visual C++ documents support for C++23 language and standard-library features by Visual Studio release.
cppreference maintains a comparative table of C++23 language and standard-library feature support across compilers and standard-library implementations.
History
In February 2020, at the final meeting for C++20 in Prague, WG21 discussed an early overall plan for C++23: The roadmap proposed library support for coroutines, a modular standard library, executors, and networking. This was an early plan rather than a guarantee that all proposals would be included; executors and networking were not included in the final C++23 standard.
The planned in-person WG21 meeting in Varna in June 2020 was cancelled because of the COVID-19 pandemic, and the committee shifted to remote meetings and work. The planned in-person meetings in New York and Kona, Hawaii were also replaced by virtual meetings. WG21 meetings remained virtual until November 2022; the November 2022 and February 2023 meetings were hybrid. The standard was technically finalized by WG21 at the hybrid meeting in Issaquah in February 2023.
WG21 used straw polls during virtual meetings to gauge consensus on proposed changes. The meeting-by-meeting summaries below identify proposals or defect resolutions that received positive straw polls; a straw poll was not itself final ISO publication approval.
November 2020
The WG21 minutes record positive straw polls on the following items at the virtual meeting of 9 November 2020:
Literal suffixes for std::size_t and the corresponding signed type
A member function contains for std::basic_string and std::basic_string_view, to check whether or not the string contains a given substring or character
Use of forwarding references in format arguments to allow std::generator-like types.
Added the std::pmr::stacktrace alias for std::basic_stacktrace<std::pmr::polymorphic_allocator<std::stacktrace_entry>>.
Changes in ranges library:
Refined definition of a view.
Replacing function template std::ranges::istream_view with alias templates std::ranges::istream_view, std::ranges::wistream_view, and customization point object std::views::istream.
zip range adaptor family:
zip_view
zip_transform_view
adjacent_view (and std::views::pairwise being equivalent to std::views::adjacent<2>)
adjacent_transform_view (and std::views::pairwise_transform being equivalent to std::views::adjacent_transform<2>)
Heterogeneous erasure overloads for associative containers.
Every specialization of std::span and std::basic_string_view is trivially copyable.
Adding conditional noexcept specifications to std::exchange.
Revamped specification and use of integer-class types.
Clarified that the C-compatibility headers remain supported and are no longer deprecated, while their use is discouraged in C++-only code that does not need C interoperability.
February 2022
The WG21 minutes record positive straw polls on the following proposals at the virtual meeting of 7 February 2022:
Allowed attributes on the function call operator of a lambda
A type trait to detect reference binding to temporary
Making std::unique_ptrconstexpr
Pipe support for user-defined range adaptors
ranges::iota, ranges::shift_left and ranges::shift_right
views::join_with
Windowing range adaptors: views::chunk and views::slide
views::chunk_by
July 2022
The WG21 minutes record positive straw polls on the following proposals and defect resolutions at the virtual meeting of 25 July 2022:
Made rewriting equality in expressions less of a breaking change.
Reverted the deprecation of bitwise assignment to volatile variables.
Added the #warning preprocessor 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 constexpr functions to never be constant expressions.
Simplified some implicit move rules from C++20 and allowed implicit move when returning an rvalue reference.
Added named universal character escapes, which allow Unicode characters to be referred to by name. For example, U'\N{LATINCAPITALLETTERAWITHMACRON}' is equivalent to U'\u0100'.
Relaxed restrictions on using pointers and references of unknown origin in constant expressions.
Allowed implementations to support extended floating-point types in addition to the three standard floating-point types. Where supported, the optional header <stdfloat> provides aliases such as std::float16_t, std::float32_t, std::float64_t, std::float128_t and std::bfloat16_t, with corresponding literal suffixes such as f16, f32, f64, f128 and bf16 (and uppercase forms), as well as relevant standard-library overloads.
Added the [[assume(expression)]] attribute, which lets an implementation assume that the expression is true for optimization purposes; it is not a run-time assertion.
Required implementations to support UTF-8 encoded source files as a portable source encoding.
Allowed arrays of char and unsignedchar to be initialized from UTF-8 string literals, as a compatibility measure for char8_t.
Relaxed the requirement for wchar_t to represent all members of the extended character set, accommodating implementations in which wide characters use UTF-16.
Added std::mdspan, a multidimensional array view analogous to std::span.
The flat associative-container adaptors std::flat_map, std::flat_multimap, std::flat_set and std::flat_multiset were added to the standard library.
Added std::print and std::println for formatted output, including output to standard output.
Added the named modules std and std.compat for importing the standard library.
Added support for exclusive mode fstreams, analogous to the "x" flag in fopen.
Allowed std::format to handle ranges, tuples, and other containers.
Added std::forward_like.
Added an rvalue-qualified std::basic_string::substr() && overload, allowing substring extraction from an rvalue string to reuse its storage where applicable.
Added std::generator, a coroutine generator that models std::ranges::input_range.
Added new algorithms: ranges::find_last, ranges::contains, and ranges fold algorithms.
Made std::tuple compatible with other tuple-like objects.
Added explicit lifetime-management functions for implicit-lifetime types.
Made std::bitset and integral overloads of std::to_chars and std::from_charsconstexpr-compatible.
Adding move-only types support for comparison concepts.
Allowing ranges iterators to be used as inputs to non-ranges algorithms.
Relaxing range adaptors to allow for move-only types.
November 2022
The WG21 minutes record positive straw polls on the following proposals and defect resolutions at the hybrid meeting of 7 November 2022:
Allowed operator[] to be static.
Allowed static and thread_local variables to appear in constexpr functions if they are usable in constant expressions.
consteval propagates upwards, that is, certain existing constexpr functions become consteval functions 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 for loop to cover the entire loop.
Reverted the deprecation of (all, not just bitwise) compound assignment to volatile variables.
↑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.