Herb Sutter's Blog, page 3
July 29, 2024
cppfront: Midsummer update
Over the winter and spring I spent a bunch of time building my essay “C++ safety, in context” and the related ACCU 2024 safety keynote, and on behind-the-scenes work toward improving C++ memory safety that you’ll be hearing more about in the coming months (including a lock-free data structure that’s wait-free and constant-time for nearly all operations; that was fun to develop and could be useful for making certain existing C and C++ code safer, we’ll see). Safety and simplicity are the two core things I want to try to dramatically improve in C++, and are why I’m doing my cppfront experiment, so although the above absorbed some time away from cppfront coding it all contributes to the same goal. (If you don’t know what cppfront is, please see the CppCon 2022 talk for an overview, and the CppCon 2023 talk for an update and discussion of why cppfront is pursuing this evolution strategy that’s different from other projects’. “Cpp2” is the shorthand name for my experimental “C++ syntax 2,” and cppfront is the open-source compiler that compiles it.)
So now it’s time for a cppfront update with some highlights of what’s been happening since the last time I posted about it here:
Wrote Cpp2 and cppfront documentation & started numbered releasesCppfront 0.7.0 (Mar 16, 2024), new things include:A “tersest” function syntax, e.g.: :(x,y) x>ySupport all C++23 and draft C++26 headers that have feature test flagsTracked contracts changes in WG21 (e.g., P2661R1)Generate Cpp1 postfix inc/dec in term of prefixAllow trailing commas in listsMore CICppfront 0.7.1 (Jul 10, 2024), new things include:Added .. non-UFCS members-only call syntaxAllow x: const = init; and x: * = init; (const and pointer deduction without explicit _ placeholder)Allow concatenated string literalsFaster compile time when doing heavy reflection and code generationAdded -quiet and -cwdCppfront 0.7.2 (Jul 27, 2024), new things include:Added range operators ... and ..= Added a compile-time @regex metafunction via reflection and code generation, by Max SagebaumAdded support for function types (e.g., std::function< (i: inout int) -> forward std::string >)Added support for C++23 (P2290) delimited hexadecimal escapesUpdated acknowledgments: Thank you!
Thank you to all these folks who have participated in the cppfront repo by opening issues and PRs, and to many more who participated on PR reviews and comment threads! These contributors represent people from high school and undergrad students to full professors, from commercial developers to conference speakers, and from every continent (except Antarctica… I think…).
Cpp2 and cppfront documentation
As of this spring, we now have Cpp2 and cppfront documentation! Last fall at CppCon 20243, the #1 cppfront request was “please write documentation!” So now that the language is stable, over the winter I got up and running with MkDocs via James Willett’s wonderful YouTube tutorial. Thanks to everyone who provided feedback and fixes!
Official releasesWith documentation in place and a stable language, I felt it was time to start numbering releases. There have been three releases so far… here are each one’s highlights.
Cppfront 0.7.0 (Mar 16, 2024)Initial feature set complete, including documentation. Here are a few highlights added since my September 2023 update blog post:
Added a “tersest” function syntax. Functions, including unnamed function expressions (aka lambdas), that do nothing but return an expression can now omit everything between ) and the expression. Here’s an example… note that this is a whole program, because compiling in -pure-cpp2 mode by default makes the entire standard library is available (efficiently imported as the std module if your compiler supports that):
main: () = { vec: std::vector = (1, 3, 5, 2, 4, 6); std::ranges::sort( vec, :(x,y) x>y ); for vec do (e) std::cout << e; // prints: 654321}
If, like me, you’re quite used to UFCS, you can also write this to put vec. first, which means the same thing: vec.std::ranges::sort( :(x,y) x>y );
And with a using namespace std::ranges nearby, you can write just vec.sort( :(x,y) x>y ); … Now, that’s how I like to write clean C++20 code, and it is indeed (after lowering) just all-ordinary C++20 code.
Support all C++23 and draft C++26 headers that have feature test flags. When you use -import-std or -include-std to make the whole C++ standard library available, cppfront tracks the ever-growing list of standard headers so that you can always use cppfront with the latest Standard C++.
Tracked contracts changes in WG21 (e.g., P2661R1). As soon as the committee’s contracts subgroup decided to switch from notation like [[pre: expression]] to pre( expression ), I made the same change in cppfront. Note that cppfront still goes beyond the “minimum viable product” being proposed for C++23, because cppfront has always supported things like contract groups and customizable violation handlers. I also upgraded the contracts implementation to guarantee any contract’s expression will not be evaluated at all unless the contract is actually being checked, plus I provide an explicitly unevaluated group that is never evaluated to express contracts that are for static analyzers only (they can contain any grammatically valid expressions).
Generate Cpp1 postfix increment/decrement in terms of prefix. Cpp2 allows only “increment/decrement in place” operators, but when lowering to Cpp1 it generates both that and the “increment/decrement and return old value” Cpp1 operators. You can write a type in Cpp2 syntax that provides the operator once, and both versions are available to Cpp1 code that consumes the Cpp2-authored type (which is just an ordinary C++ type anyway, just written in a different syntax).
Allow trailing commas in lists. I got lots of requests for this, and Cpp2 now allows an extra redundant trailing comma at the end of any comma-delimited list. This is desirable because it lets programmers have cleaner source code diffs when adding a parameter or argument (if the source already has parameters/arguments on their own lines), and it slightly simplifies metafunctions’ code generation because they don’t have to track whether to suppress the last comma (and I think it’s important to make source code generation use cases easier). For a bit more rationale, see this Issue comment that goes with the commit.
More CI: Besides build tests, added regression testing scripts and workflows. Thanks to Jaroslaw Glowacki and Johel Ernesto Guerrero Peña!
Cppfront 0.7.1 (Jul 10, 2024)This release added several features.
Added .. non-UFCS members-only syntax. This syntax invokes only a member function, and will not fall back to free functions. The main motivation was to provide a way to experiment if the UFCS logic noticeably added to Cpp1 compile times; I haven’t been able to verify that they cause much more compile time impact than an average-complexity line of code, but this way people can try it out. Example: mystring..append("foo");
Allow x: const = init; and x: * = init; without writing the _ type wildcard, in cases where all we want to say is that the deduced type is const or a pointer.
Allow concatenated string literals. For example, writing "Hello " "(name$)\n" now works. Note in that example that one string literal doesn’t use interpolation, and one does, and that’s fine.
Faster compile time when doing heavy reflection and code generation. I haven’t had to optimize cppfront much yet because it’s been fast in all my uses, but Max Sagebaum exercised metafunctions heavily for @regex (covered below, in 0.7.2) and made me find another ~100x performance improvement (thanks Max!). — This is the second optimization I can recall in cppfront so far, after Johel Ernesto Guerrero Peña‘s ~100x improvement last year by just changing the four uses of std::regex to find_if on a sorted vector of strings.
Added some command-line options: -quiet (thanks Marek Knápek for the suggestion!) and -cwd (thanks Fred Helmesjö for the PR!) command-line options.
Cppfront 0.7.2 (Jul 27, 2024)This release added a few features, a couple of which are major and/or long-requested.
Added range operators ... and ..= . . I deliberately chose to make the default syntax ... mean a half-open range (like Rust, unlike Swift) so that it is bounds-safe by default for iterator ranges; for a “closed” range that includes the last value, use ..= . For example: iter1 ... iter2 is a range that safely doesn’t include iter2, as we expect for STL iterators; and 1 ..= 100 is a range of integer values that includes 100. For more, see the documentation here: ... and ..= range operators.
Added a compile-time @regex metafunction by Max Sagebaum. @regex uses compile-time reflection and source code generation via Cpp2 metafunctions to achieve compile- and run-time performance comparable to Hana Dusíková‘s groundbreaking CTRE library that uses today’s templates and other metaprogramming for the compile-time work. Thanks, Max! See the last ~10 minutes of my ACCU 2024 talk for an overview of CTRE and @regex and our initial performance results… the talk was a preview of the PR that was then merged in 0.7.2.
Add support for function types. You can now write a function signature as a type, such as to use with std::function (e.g., std::function< (i: inout int) -> forward std::string >) or to write a pointer to a function (e.g., pfn: *(i: inout int) -> forward std::string). For more, see the documentation here: Using function types. Thanks to Johel Ernesto Guerrero Peña for all his contributions toward function types in particular, and for his scores of merged PRs over the past year!
Added support for C++23 (P2290) delimited hexadecimal escapes. Didn’t notice these were in C++23? Neither did I! Thanks to Max Sagebaum for the PR to add support for escapes of the form \x{62}… you can now use them in Cpp2 code and they’ll work if your Cpp1 compiler understands them. Note that cppfront itself and its generated code don’t have a dependency on them; the cppfront philosophy is to “rely only on C++20 [in cppfront and its code gen requirements] for compatibility and portability, and support C++23/26 as a ‘light-up’ [people can use those features in their own Cpp2 code and they work if their Cpp1 compiler supports them].”
What’s nextFor the rest of the year, I plan to:
Have regular cppfront releases, and post an update here for each one.Share some updates about the cppfront license (currently it’s a non-commercial-use-only CC license to emphasize that this has been a personal experiment).But first, in just seven (7) weeks, I’ll be at CppCon to give a talk that I plan to be in three equal parts:
C++26 progress, and why C++26 is shaping up to be the most important C++ release since C++11.C++ memory safety problems and solutions (update of my ACCU talk).Cppfront update.I look forward to seeing many of you there!
July 2, 2024
Trip report: Summer ISO C++ standards meeting (St Louis, MO, USA)
On Saturday, the ISO C++ committee completed its fourth meeting of C++26, held in St Louis, MO, USA.
Our host, Bill Seymour, arranged for high-quality facilities for our six-day meeting from Monday through Saturday. We had over 180 attendees, about two-thirds in-person and the others remote via Zoom, formally representing over 20 nations. At each meeting we regularly have new attendees who have never attended before, and this time there were nearly 20 new first-time attendees, mostly in-person. To all of them, once again welcome!
We also often have new nations joining, and this time we welcomed participants formally representing Kazakhstan and India for the first time. We now have 29 nations who are regular formal participants: Austria, Bulgaria, Canada, China, Czech Republic, Denmark, Finland, France, Germany, Iceland, India, Ireland, Israel, Italy, Japan, Kazakhstan, Republic of Korea, The Netherlands, Norway, Poland, Portugal, Romania, Russia, Slovakia, Spain, Sweden, Switzerland, United Kingdom, and United States.
Here is a Saturday group photo of the in-person attendees right after the meeting adjourned (some had already left to catch flights). Thanks to John Spicer for taking this photo. Our host Bill Seymour is seated in the front row with the yellow dot. Thank you very much again, Bill, for having us!


The committee currently has 23 active subgroups, 16 of which met in parallel tracks throughout the week. Some groups ran all week, and others ran for a few days or a part of a day and/or evening, depending on their workloads. You can find a brief summary of ISO procedures here.
This time, the committee adopted the next set of features for C++26, and made significant progress on other features that are now expected to be complete in time for C+26.
Three major features made strong progress:
P2300 std::execution for concurrency and parallelism was formally adopted to merge into the C++26 working paperP2996 Reflection was design-approved, and is now in specification wording review aiming for C++26P2900 Contracts made considerable progress and has a chance of being in C++26P2300 std::execution formally adopted for C++26The major feature approved to merge into the C++26 draft standard was P2300 “std::execution” (aka “executors”, aka “Senders/Receivers”) by Michał Dominiak, Georgy Evtushenko, Lewis Baker, Lucian Radu Teodorescu, Lee Howes, Kirk Shoop, Michael Garland, Eric Niebler, and Bryce Adelstein Lelbach. It had already been design-approved for C++26 at prior meetings, but it’s a huge paper so the specification wording review by Library Wording subgroup (LWG) took extra time, and as questions arose the paper had to iterate with LEWG for specific design clarifications and tweaks.
P2300 aims to support both concurrency and parallelism. The definitions I use: Concurrency means doing independent work asynchronously (e.g., on different threads, or using coroutines) so that each can be responsive and progress at its own speed. Parallelism means using more hardware (cores, vector units, GPUs) to perform a single computation faster, which is the key to re-enabling the “free lunch” of being able to ship an application executable today that just naturally runs much faster on newer hardware with more compute throughput that becomes available in the future (most of which new throughput now ships in the form of more parallelism).
For concurrency, recall that in C++20 we already added coroutines, but in their initial state they were more of a “portable toolbox for writing coroutines” than a fully integrated feature (e.g., we can’t co_await a std::future with just what’s in the standard). Since then, we knew we’d want to add libraries on top to make coroutines easier to use, including std::future integration and a std::task library, which are still in progress. One of the big reasons to love std::execution is that it works well with coroutines, and is the biggest usability improvement yet to use the coroutine support we already have.
Ville Voutilainen reports writing a concurrent chunked HTTPS download that integrates nicely with C++20 coroutines’ co_await and a Qt UI progress bar, using P2300’s reference implementation (plus a sender-aware task type which is expected to be standardized in the future, but third-party ones like the exec::task below work today), together with his own Qt adaptation code (about 180 lines, which will eventually ship as part of Qt). The code is short enough to show here:
exec::task HttpDownloader::doFetchWithCoro(){ bytesDownloaded = 0; contentLength = 0; reportDownloadProgress(); req = QNetworkRequest(QUrl(QLatin1String("https://ftp.funet.fi/pub/Linux/kernel... QNetworkReply* reply = nam.head(req); co_await qObjectAsSender(reply, &QNetworkReply::finished); updateContentLength(reply, contentLength); contentLengthUpdated(contentLength); reply->deleteLater(); while (bytesDownloaded != contentLength) { req = setupRequest(req, bytesDownloaded, chunkSize); QNetworkReply* get_reply = nam.get(req); co_await qObjectAsSender(get_reply, &QNetworkReply::finished); updateBytesDownloaded(get_reply, bytesDownloaded); reportDownloadProgress(); get_reply->deleteLater(); }}For parallelism, see the December 2022 HPC Wire article “New C++ Sender Library Enables Portable Asynchrony” by Eric Niebler, Georgy Evtushenko, and Jeff Larkin, which describes the cross-platform parallel performance of std::execution. “Cross-platform” means across different parallel programming models, using both distributed-memory and shared-memory, and across different computer architectures. (HT: Thanks Mark Hoemmen and others for reminding us about this article.) The NVIDIA coauthors of P2300 report that parallel performance is on par with CUDA code.
Mikael Simberg reports that another parallelism example from the HPC community to show off P2300 is DLA_Future (GitHub), which implements a distributed CPU/GPU eigensolver. It optionally uses std::execution’s reference implementation, and plans to use std::execution unconditionally once it ships in C++26 standard libraries. In that repo, one advanced example is this distributed Cholesky decomposition code (GitHub) (note: it still uses start_detached which was recently removed, and plans to use async_scope once available).
See also P2300 itself for more examples of both techniques.
Reflection design-approved for C++26The Language Evolution working group (EWG) approved the design of the reflection proposal P2996R2 “Reflection for C++26” by Wyatt Childers, Peter Dimov, Barry Revzin, Andrew Sutton, Faisal Vali, and Daveed Vandevoorde and it has now begun language specification wording review, currently on track for C++26. (Updated to add: The Library Evolution working group (LEWG) is still reviewing the library part of the design.)
This is huge, because reflection (including generation) will be by far the most impactful feature C++ has ever added since C++98, and it will dominate the next decade and more of C++ usage. It’s a watershed event; a sea change in C++. I say this for three reasons:
First, reflection and generation are the biggest power tool C++ has ever seen to improve library building: It will enable writing C++ libraries that were infeasible or impossible before, and its impact on writing libraries will likely be bigger than all the other library-writing improvements combined that the language has added from C++11 until now (e.g., lambdas, auto, if constexpr, requires, type traits).
Second, reflection and generation will simplify C++ language evolution: It will reduce the need to add as many future one-off or “narrow” language extensions to C++, because we will be able to write many of them as compile-time libraries in ordinary C++ consteval code using reflection and generation. That by itself will help slow down the future growth of complexity of the language. And it has already been happening; in recent years, SG7 (the subgroup responsible for compile-time programming) has redirected some narrow language proposals to explore how to write them using reflection instead.
Third, reflection and generation is the foundation for another potential way to dramatically simplify how we write C++ code, namely my metaclasses proposal which is “just” a small (but powerful) thin extension layered on top of reflection and generation… for details, see the Coda at the end of this post.
Still aiming for C++26 timeframe: ContractsWe spent four full days of subgroup time on the contracts proposal P2900 “Contracts for C++” by Joshua Berne, Timur Doumler, Andrzej Krzemieński, Gašper Ažman, Tom Honermann, Lisa Lippincott, Jens Maurer, Jason Merrill, and Ville Voutilainen: One and a half days in language design (EWG) on Monday afternoon and Tuesday, a parallel session in the safety group (SG23) on Tuesday, two days in the Contracts subgroup (SG21) on Wednesday and Thursday, then a quarter-day back in EWG on Friday after lunch for another session on virtual function contracts. In all, we worked through many design issues and made good progress toward consensus on several of them. We still have further work to do in order to build consensus on other open design questions, but the consensus is gradually improving and the list of open questions is gradually getting shorter… we’ll see! I’m cautiously optimistic that we have a 50-50 chance of getting contracts in C++26, which means that we will have to iron out the remaining differences within the next 11 months to meet C++26’s feature-freeze no-later-than hard deadline next June.
Adopted for C++26: Core language changes/featuresHere are some additional highlights… note that these links are to the most recent public version of each paper, and some were tweaked at the meeting before being approved; the links track and will automatically find the updated version as soon as it’s uploaded to the public site.
The core language adopted 6 papers, including the following…
P0963R3 “Structured binding declaration as a condition” by Zhihao Yuan. This allows structured binding declarations with initializers appearing in place of the conditions in if, while, for, and switch statements, so you can decompose more conveniently and take a branch only if the returned non-decomposed object evaluates to true. Thanks, Zhihao!
Adopted for C++26: Standard library changes/featuresIn addition to P2300 std::execution, already covered above, the standard library adopted 11 other papers, including the following…
The lowest-numbered paper approved, which means it has been “baking” for the longest time, is something some of us have been awaiting for a while: P0843R11 “inplace_vector” by Gonzalo Brito Gadeschi, Timur Doumler, Nevin Liber, and David Sankel. The paper’s overview says it all – thank you, authors!
This paper proposes inplace_vector, a dynamically-resizable array with capacity fixed at compile time and contiguous inplace storage, that is, the array elements are stored within the vector object itself. Its API closely resembles std::vector, making it easy to teach and learn, and the inplace storage guarantee makes it useful in environments in which dynamic memory allocations are undesired.
This container is widely-used in the standard practice of C++, with prior art in, e.g., boost::static_vector or the EASTL, and therefore we believe it will be very useful to expose it as part of the C++ standard library, which will enable it to be used as a vocabulary type.
P3235R3 “std::print more types faster with less memory” by Victor Zverovich gets my vote for the “best salesmanship in a paper title” award! If you like std::print, this is more, faster, sleeker (who wouldn’t vote for that?!) by expanding the applicability of the optimizations previously delivered in P3107 which initially were applied to only built-in type and string types, and now work for more standard library types. Thanks for all the formatted I/O, Victor!
P2968R2 “Make std::ignore a first-class object” by Peter Sommerlad formally blesses the use of std::ignore on the left-hand side of an assignment. Initially std::ignore was only meant to be used with std::tie, but many folks noticed (and recommended and relied on) that on every implementation you can also use it to ignore the result of an expression by just writing std::ignore = expression;. Even the C++ Core Guidelines’ ES.48 “Avoid casts” recommends “Use std::ignore = to ignore [[nodiscard]] values.” And as of C++26, that advice will be upgraded from “already works in practice” to “officially legal.” Thank you, Peter!
Other progressAll subgroups continued progress, more of which will no doubt be covered in other trip reports. Here are a few more highlights…
SG1 (Concurrency): Discussed 24 papers, and progressed the “zap” series of papers. To the happiness of many people (including me), concurrent_queue is finally nearing completion! A concurrent queue is one of the foundational concurrency primitives sorely missing from the standard library, and it’s great to see it coming closer to landing.
SG6 (Numerics): More progress on several proposals including a quantities-and-units library.
SG7 (Compile-Time Programming): Forwarded six more papers to the main subgroups, most of them reflection-related.
SG9 (Ranges): Continued working on ranges extensions for C++26, with good progress.
SG15 (Tooling): Starting to approve sending Ecosystem papers to the main subgroups, such as metadata formats and support for build systems.
SG23 (Safety): Reviewed several different proposals for safety improvement. Voted favorably to support P3297 “C++26 needs contracts checking” by Ryan McDougall, Jean-Francois Campeau, Christian Eltzschig, Mathias Kraus, and Pez Zarifian.
Thank you to all the experts who worked all week in all the subgroups to achieve so much this week!
What’s nextOur next meeting will be in Wrocław, Poland in November hosted by Nokia.
Thank you again to the over 180 experts who attended on-site and on-line at this week’s meeting, and the many more who participate in standardization through their national bodies!
But we’re not slowing down… we’ll continue to have subgroup Zoom meetings, and then in just a few months from now we’ll be meeting again in person + Zoom to continue adding features to C++26. Thank you again to everyone reading this for your interest and support for C++ and its standardization.
Coda: From reflection to metaclass functions and P0707The reason I picked reflection and generation to be the first “major” feature from Cpp2 that I brought to the committee in 2017, together with a major application use case, in the form of my “metaclasses” paper P0707, is because it was the biggest source of simplification in Cpp2, but it was also the riskiest part of Cpp2 — it was the most “different from what we do in C++” so I was not sure the committee and community would embrace the idea, and it was the most “risky to implement” because nothing like using compile-time functions to help generate class code had ever been tried for C++.
Most of my initial version of P0707 was a plea of ‘here’s why the committee should please give us reflection and generation.’ When I first presented it to the committee at the Toronto 2017 meeting immediately following the reflection presentation, I began my presentation with something like: “Hi, I’m Herb, and I’m their customer,” pointing to the reflection presenters, “because this is about what we could build on top of reflection.” That is still true; the main reason I haven’t updated P0707 since 2019 is because I haven’t needed to… the reflection work needs to exist first, and it has been continually progressing.
Historical note: Andrew Sutton’s Lock3 reflection implementation was created for, and funded by, my project that is now called Cpp2 , but which back then was called Cppx and used the Lock3 Clang-based reflection implementation; that’s why the Lock3 implementation has been available at cppx.godbolt.org (thanks again, Matt! you’re a rock star). C++20 consteval also came directly from this work, because we realized we would need functions that must run only at compile time to deal with static reflections and generation.
Now that reflection is landing in the standard, I plan to update my P0707 paper to finish proposing metaclasses for ISO C++. P0707 metaclasses (aka type metafunctions) are actually just a thin layer on top of P2996. To see why, consider this simple code:
// Example 1: Possible with P2996consteval { generate_a_widget_class(); } // let’s say that executing this consteval function generates something like: // class widget { void f() { std::cout << "hello"; } };With P2996, Example 1 can write such a consteval function named generate_a_widget_class that can be invoked at compile time and generates (aka injects) that widget type as if it had been hand-written by the programmer at the same point in source code.
Next, let’s slightly generalize the example by giving it an existing type’s reflection as some input to guide what gets generated:
// Example 2: Possible with P2996 (^ is the reflection operator)class gadget { /*...*/ }; // written by the programmer by handconsteval{ M( ^gadget ); } // generates widget from the reflection of gadget // now this generates something like: // class widget { /* some body based on the reflection of what’s in gadget */ };Still with just P2996, Example 2 can write such a consteval function named M that will generate the widget class as-if was hand-written by the programmer at this point in source code, but with the ability to refer to ^gadget… for example, perhaps widget will echo some or all the same member functions and member variables as gadget, and add additional things.
And, just like that, we’ve suddenly arrived at P0707 metaclasses because all the Lock3 implementation of Cpp2 (then Cppx) metaclasses did is to “package up Example 2,” by providing a syntax to apply the consteval function M to the type being defined:
// Example 3: class(M) means to apply M to the class being defined// (not yet legal C++)class(M) widget{ /*...*/ }; // this proposed language feature would emit something like the following: // namespace __prototype { class widget { /*...*/ }; } // consteval{ M( ^__prototype::widget ); } // generates widget from __prototype::widgetHistorical note: My initial proposal P0707R0 proposed the syntax “M class” (e.g., interface class, value class), and the SG7 subgroup gave feedback that it preferred “class(M)” (e.g., class(interface), class(value)) to make parsing easier. I’m fine with that; the syntax is less important, what matters is getting the expressive power.
So my plan for my next revision of P0707 is to propose class(M) syntax for Standard C++ as a further extension on top of P2996 reflection, to be implemented just like Example 3 above (and as Lock3 already did since 2017, so we know it works).
Why is that so important to simplifying C++?
First, as I show in P0707, it means that we can make classes much easier and safer to write, without wrong defaults and bug-prone boilerplate code. We can stop teaching the “Rules of 0/1/3/5,” and stop teaching =delete to get rid of generated special functions we didn’t want, because when using metafunctions to write classes we’re always using a convenient word to opt into a group of defaults for the type we’re writing and can get exactly the ones we want.
Second, we can write a Java/C#-style “class(interface)” without adding a special “interface” feature to the language as a separate type category, and with just as good efficiency and usability as languages that bake interface into the language. We can add “class(value)” to invoke a C++ function that runs at compile time to get the defaults right for value types without a new language feature hardwired into the compiler. We can add class(safe_union) and class(flag_enum) and much more.
Third, as I expressed in P0707, I hope reflection+generations+metafunctions can replace Qt MOC, COM IDL, C++/CLI extensions, C++/CX IDL, all of which exist primarily because we couldn’t express things in Standard C++ that we will now be able to express with this feature. I’m responsible for some of those nonstandard technologies; I led the design of C++/CLI and C++/CX, and one of my goals for reflection+generation+metafunctions is that I hope I will never need to design such language extensions again, by being able to express them well in normal (future) Standard C++. And I’m not alone; my understanding is that many of the vendors who own technologies like the above are already eagerly planning to responsibly transition such currently-add-on technologies to a standard reflection-and-generation based implementation, once reflection and generation are widely available in C++ compilers.
If you’re interested in more example of how metafunctions can work, I strongly recommend re-watching parts of two talks:
The middle section of my CppCon 2023 talk, starting around 18:50 up to 44:00, which shows many examples that work today using my cppfront compiler to translate them to regular C++, including detailed walkthroughs of the “enum” and “union” metaclass functions (in Cpp2 syntax, but they will work just as well as a minor extension of today’s C++ syntax as described above).My original CppCon 2017 talk starting a few minutes in (an earlier version of this talk premiered initially at ACCU 2017), which demonstrates the approach and shows the first few examples working on the early Lock3 reflection implementation. The syntax has changed slightly, but the entire talk is still super current in 2024 as the reflection and generation it relies upon is now on its way to (finally!) landing in the standard.I’m looking forward to finally resume updating P0707 to propose adding the rest of the expressive power it describes, as an extension to today’s C++ standard syntax, built on top of Standard C++26 (we hope!) reflection and generation. I hope to bring an updated proposal to our next meeting in November. My first step will be to try writing P0707 metafunctions in P2996 syntax to validate everything is there and works as I expect. So far, the only additional reflection support I know of that I’ll have to propose adding onto today’s P2996 is is_default_accessiblity() (alongside is_public() et al.) to query whether a member has the “default” accessibility of the class, i.e., is written before any public: or protected: or private: access specifier; that’s needed by metafunctions like “interface” that want to apply defaults, such as to make functions public and pure virtual by default without the user having to write public: or virtual or =0.
Safety is very important and we’ll be working hard on that too. But I would be remiss not to emphasize that the arrival of reflection (including generation) is a sea change that will drive of our next decade and more of C++… it’s really that big a deal, a rising tide that will lift all other boats including safety and simplicity as well. Starting soon, for many years we won’t be able to go to a C++ conference whose program doesn’t heavily feature reflection… and I’m not saying that just because I know several reflection talks have been accepted for CppCon 2024 two months from now; this really will be talked about and heavily used everywhere across our industry because there’s so much goodness to learn and use in this powerful feature.
June 7, 2024
Podcast: Interview with Software Engineering Daily
Also in April, I was interviewed by Jordi Mon Companys for Software Engineering Daily, and that interview was just published on the SE Daily podcast.
Here is a copy of the page’s additional details, including a transcript link at bottom.

The U.S. government recently released a report calling on the technical community to proactively reduce the attack surface area of software infrastructure. The report emphasized memory safety vulnerabilities, which affect how memory can be accessed, written, allocated, or deallocated.
The report cites this class of vulnerability as a common theme in the some of the most infamous cyber events, such as the Morris worm of 1988, the Heartbleed vulnerability in 2014, and the Blastpass exploit of 2023.
Herb Sutter works at Microsoft and chairs the ISO C++ standards committee. He joins the show to talk about C++ safety.

Jordi Mon Companys is a product manager and marketer that specializes in software delivery, developer experience, cloud native and open source. He has developed his career at companies like GitLab, Weaveworks, Harness and other platform and devtool providers. His interests range from software supply chain security to open source innovation. You can reach out to him on Twitter at @jordimonpmm.
June 4, 2024
April talk video posted: “Safety, Security, Safety[sic] and C/C++[sic]”
Many thanks to ACCU for inviting me back again this April. It was my first time back to ACCU (and only my second trip to Europe) since the pandemic began, and it was a delight to see many ACCUers in person again for the first time in a few years.
I gave this talk, which is now up on YouTube here:
It’s an evolved version of my March essay “C++ safety, in context.” I don’t like just repeating material, so the essay and the talk each covers things that the other doesn’t. In the talk, my aim was to expand on the key points of the essay with additional discussion and data points, including new examples that came up in the weeks between the essay and the talk, and relating it to ongoing ISO C++ evolution for safety already in progress.
The last section of the talk is a Cppfront update, including some interesting new results regarding compile- and run-time performance using metafunctions. One correction to the talk: I looked back at my code and I had indeed been making the mistake of creating a new std::regex object for each use, so that accounted for some of the former poor performance. But I retested and found that mistake only accounted for part of the performance difference, so the result is still valid: Removing std::regex from Cppfront was still a big win even when std::regex was being used correctly.
I hope you find the talk interesting and useful. Thanks very much to everyone who has contributed to C++ safety improvement explorations, and everyone who has helped with Cppfront over the past year and a half since I first announced the project! I appreciate all your input and support for ISO C++’s ongoing evolution.
April 3, 2024
Pre-ACCU interview video is live
On Friday, I sat down with Kevin Carpenter to do a short (12-min) interview about my ACCU talk coming up on April 17, and other topics.
Apologies in advance for my voice quality: I’ve been sick with some bug since just after the Tokyo ISO meeting, and right after this interview I lost my voice for several days… we recorded this just in time!
Kevin’s questions were about these topics in order (and my short answers):
Chatting about my ACCU talk topics (safety, and cppfront update)Is it actually pretty easy to hop on a stage and talk about C++ for an hour (nope; or at least for me, not well)In ISO standardization, how to juggle adding features vs. documenting what’s done (thanks to the Reddit trip report coauthors!)ISO C++ meetings regularly have lots of guests, including regularly high school classes (yup, that’s a thing now)Safety and C++ and cppfront topicsKevin’s outro: “Get your ticket for ACCU now!”March 25, 2024
Effective Concurrency course & upcoming talks
With the winter ISO meeting behind us, it’s onward into spring conference season!
ACCU Conference 2024. On April 17, I’ll be giving a talk on C++’s current and future evolution, where I plan to talk about safety based on my recent essay C++ safety, in context,” and progress updates on cppfront. I’m also looking forward to these three keynoters:
Laura Savino, who you may recall gave an outstanding keynote at CppCon 2023 just a few months ago. Thanks again for that great talk, Laura!Björn Fahller, who not only develops useful libraries but is great at naming them (Trompeloeil, I’m looking at you! [sic]).Inbal Levi, who chairs one of the two largest subgroups in the ISO C++ committee (Library Evolution Working Group, responsible for the design of the C++ standard library) and is involved with organizing and running many other C++ conferences.Effective Concurrency online course. On April 22-25, I’ll be giving a live online public course for four half-days, on the topic of high-performance low-latency coding in C++ (see link for the course syllabus). The times of 14.00 to 18.00 CEST daily are intended to be friendly to the home time zones of attendees anywhere in EMEA and also to early risers in the Americas. If you live in a part of the world where these times can’t work for you, and you’d like another offering of the course that is friendlier to your home time zone, please email Alfasoft to let them know! If those times work for you and you’re interested in high performance and low latency coding, and how to achieve them on modern hardware architectures with C++17, 20, and 23, you can register now.
Beyond April, later this year I’ll be giving talks in person at these events:
September: CppCon in Aspen, CO, USANovember: Meeting C++ in Berlin, GermanyNovember: code::dive in Wrocław, PolandDetails for the November conferences will be available on their websites soon.
I look forward to chatting with many of you in person or online this year!
March 22, 2024
Trip report: Winter ISO C++ standards meeting (Tokyo, Japan)
Moments ago, the ISO C++ committee completed its third meeting of C++26, held in Tokyo, Japan. Our hosts, Woven by Toyota, arranged for high-quality facilities for our six-day meeting from Monday through Saturday. We had over 220 attendees, about two-thirds in-person and the others remote via Zoom, formally representing 21 nations. That makes it roughly tied numerically for our largest meeting ever, roughly the same attendance as Prague 2020 that shipped C++20 just a few weeks before the pandemic lockdowns. — However, note that it’s not an apples-to-apples comparison, because the pre-pandemic meetings were all in-person, and since the pandemic they have been hybrid. But it is indicative of the ongoing strong participation in C++ standardization.
At each meeting we regularly have new attendees who have never attended before, and this time we welcomed over 30 new first-time attendees, mostly in-person, who were counted above. (These numbers are for technical participants, and they don’t include that we also had observers, including a class of local high school students visiting for part of a day, similarly to how a different local high school class did at our previous meeting in Kona in November. We are regularly getting high-school delegations as observers these days, and to them once again welcome!)
The committee currently has 23 active subgroups, 16 of which met in parallel tracks throughout the week. Some groups ran all week, and others ran for a few days or a part of a day and/or evening, depending on their workloads. You can find a brief summary of ISO procedures here.
This week’s meeting: Meeting #3 of C++26At the previous two meetings in June and November, the committee adopted the first 63 proposed changes for C++26, including many that had been ready for a couple of meetings while we were finishing C++23 and were just waiting for the C++26 train to open to be adopted. For those highlights, see the June trip report and November trip report.
This time, the committee adopted the next set of features for C++26, and made significant progress on other features that are now expected to be complete in time for C+26.
Here are some of the highlights… note that these links are to the most recent public version of each paper, and some were tweaked at the meeting before being approved; the links track and will automatically find the updated version as soon as it’s uploaded to the public site.
Adopted for C++26: Core language changes/featuresThe core language adopted 10 papers, including the following…
P2573R2 “=delete(“should have a reason”)” by Yihe Li does the same for =delete as we did for static_assert: It allows writing a string as the reason, which makes it easier for library developers to give high-quality compile-time error messages to users as part of the compiler’s own error message output. Thanks, Yihe!
Here is an example from the paper that will now be legal and generate an error message similar to the one shown here:
class NonCopyable{public: // ... NonCopyable() = default; // copy members NonCopyable(const NonCopyable&) = delete("Since this class manages unique resources, \copy is not supported; use move instead."); NonCopyable& operator=(const NonCopyable&) = delete("Since this class manages unique resources, \copy is not supported; use move instead."); // provide move members instead};:16:17: error: call to deletedconstructor of 'NonCopyable': Since this class manages unique resources, copy is not supported; use move instead. NonCopyable nc2 = nc; ^ ~~P2795R5 “Erroneous behavior for uninitialized reads” by Thomas Köppe is a major change to C++ that will help us to further improve safety by providing a tool to reduce undefined behavior, especially that it removes undefined behavior for some cases of uninitialized objects.
I can’t do better than quote from the paper:
Summary: We propose to address the safety problems of reading a default-initialized automatic variable (an “uninitialized read”) by adding a novel kind of behaviour for C++. This new behaviour, called erroneous behaviour, allows us to formally speak about “buggy” (or “incorrect”) code, that is, code that does not mean what it should mean (in a sense we will discuss). This behaviour is both “wrong” in the sense of indicating a programming bug, and also well-defined in the sense of not posing a safety risk.
…
With increased community interest in safety, and a growing track record of exploited vulnerabilities stemming from errors such as this one, there have been calls to fix C++. The recent P2723R1 proposes to make this fix by changing the undefined behaviour into well-defined behaviour, and specifically to well-define the initialization to be zero. We will argue below that such an expansion of well-defined behaviour would be a great detriment to the understandability of C++ code. In fact, if we want to both preserve the expressiveness of C++ and also fix the safety problems, we need a novel kind of behaviour.
…
Reading an uninitialized value is never intended and a definitive sign that the code is not written correctly and needs to be fixed. At the same time, we do give this code well-defined behaviour, and if the situation has not been diagnosed, we want the program to be stable and predictable. This is what we call erroneous behaviour.
In other words, it is still an “wrong” to read an uninitialized value, but if you do read it and the implementation does not otherwise stop you, you get some specific value. In general, implementations must exhibit the defined behaviour, at least up until a diagnostic is issued (if ever). There is no risk of running into the consequences associated with undefined behaviour (e.g. executing instructions not reflected in the source code, time-travel optimisations) when executing erroneous behaviour.
Adding the notion of “erroneous behavior” is a major change to C++’s specification, that can help not only with uninitialized reads but also can be applied to reduce other undefined behavior in the future. Thanks, Thomas!
Adopted for C++26: Standard library changes/featuresThe standard library adopted 18 papers, including the following…
In the “Moar Ranges!” department, P1068R11 “Vector API for random number generation” by Ilya Burylov, Pavel Dyakov, Ruslan Arutyunyan, Andrey Nikolaev, and Alina Elizarova addresses the situation that, when you want one random number, you likely want more of them, and random number generators usually already generate them efficiently in batches. Thanks to their paper, this will now work:
std::array intArray;std::mt19937 g(777);std::ranges::generate_random(intArray, g);// The above line will be equivalent to this:for(auto& e : intArray) e = g();In the “if you still didn’t get enough ‘Moar Ranges!’” department, P2542 “views::concat” by Hui Xie and S. Levent Yilmaz provides an easy way to efficiently concatenate an arbitrary number of ranges, via a view factory. Thanks, Hui and Levent! Here is an example from the paper:
std::vector v1{1,2,3}, v2{4,5}, v3{};std::array a{6,7,8};auto s = std::views::single(9);std::print("{}\n", std::views::concat(v1, v2, v3, a, s)); // output: [1, 2, 3, 4, 5, 6, 7, 8, 9]Speaking of concatenation, have you ever wished you could write “my_string_view + my_string” and been surprised it doesn’t work? I sure have. No longer: P2591R4 “Concatenation of strings and string views” by Giuseppe D’Angelo adds operator+ overloads for those types. Thanks, Giuseppe, for finally getting us this feature!
P2845 “Formatting of std::filesystem::path” by Victor Zverovich (aka the King of Format) provides a high-quality std::format formatter for filesystem paths that addresses concerns about quoting and localization.
A group of papers by Alisdair Meredith removed some (mostly already-deprecated) features from the standard library. Thanks for the cleanup, Alisdair!
P2867R2 “Remove Deprecated strstreams From C++26”P2869R4 “Remove Deprecated shared_ptr Atomic Access APIs from C++26”P2872R3 “Remove wstring_convert From C++26”P3142R0 “Printing Blank Lines with println” by Alan Talbot is small but a nice quality-of-life improvement: We can now write just println() as an equivalent of println(“”). But that’s not all: See the yummy postscript in the paper. (See, Alan, we do read the whole paper. Thanks!)
Those are some of the “bigger” or “likely of wide interest” papers as just a few highlights… this week there were 28 papers adopted in all, including other great work on extensions and fixes for the C++26 language and standard library.
Aiming for C++26 timeframe: ContractsThe contracts proposal P2900 “Contracts for C++” by Joshua Berne, Timur Doumler, Andrzej Krzemieński, Gašper Ažman, Tom Honermann, Lisa Lippincott, Jens Maurer, Jason Merrill, and Ville Voutilainen progressed out of the contracts study group, SG21, and was seen for the first time in the Language (EWG) and Library (LEWG) Evolution Working Groups proper. Sessions started in LEWG right on the first day, Monday afternoon, and EWG spent the entire day Wednesday on contracts, with many of the members of the safety study group, SG23, attending the session. There was lively discussion about whether contracts should be allowed to have, or be affected by, undefined behavior; whether contracts should be used in the standard library; whether contracts should be shipped first as a Technical Specification (TS, feature branch) in the same timeframe as C++26 to gain more experience with existing libraries; and other aspects… all of these questions will be discussed again in the coming months, this was just the initial LEWG and EWG full-group design review that generated feedback to be looked at. The subgroups considered the EWG and LEWG groups’ feedback later in the week in two more sessions on Thursday and Friday, including in a joint session of SG21 and SG23.
Both SG21 and SG23 will have telecons about further improving the contracts proposal between now and our next hybrid meeting in June.
On track for targeting C++26: ReflectionThe reflection proposal P2996R2 “Reflection for C++26” by Wyatt Childers, Peter Dimov, Barry Revzin, Andrew Sutton, Faisal Vali, and Daveed Vandevoorde progressed out of the reflection / compile-time programming study group, SG7, and was seen by the main evolution groups EWG and LEWG for the first time on Tuesday, which started with a joint EWG+LEWG session on Tuesday, and EWG spent the bulk of Tuesday on its initial large-group review aiming for C++26. Then SG7 continued on reflection and other topics, including a presentation by Andrei Alexandrescu about making sure reflection adds a few more small things to fully support flexible generative programming.
Other progressAll subgroups continued progress. A lot happened that other trips will no doubt cover, but I’ll call out two things.
One proposal a lot of people are watching is P2300 “std::execution” (aka “executors”) by Michał Dominiak, Georgy Evtushenko, Lewis Baker, Lucian Radu Teodorescu, Lee Howes, Kirk Shoop, Michael Garland, Eric Niebler, and Bryce Adelstein Lelbach, which was already design-approved for C++26. It’s a huge paper (45,000 words, of which 20,000 words is the standardese specification! that’s literally a book… my first Exceptional C++ book was 62,000 words), so it has been taking time for the Library Wording subgroup (LWG) to do its detailed review of the specification wording, and at this meeting LWG spent a quarter of the meeting completing a first pass through the entire paper! They will continue to work in teleconferences on a second pass and are now mildly optimistic of completing P2300 wording review at our next meeting in June.
And one more fun highlight: We all probably suspected that pattern matching is a “ground-shaking” proposed addition to future C++, but in Tokyo during the pattern matching session there was a literal earthquake that briefly interrupted the session!
Thank you to all the experts who worked all week in all the subgroups to achieve so much this week!
What’s nextOur next meeting will be in St. Louis, MO, USA in June hosted by Bill Seymour.
Wrapping upThank you again to the over 210 experts who attended on-site and on-line at this week’s meeting, and the many more who participate in standardization through their national bodies!
But we’re not slowing down… we’ll continue to have subgroup Zoom meetings, and then in just three months from now we’ll be meeting again in person + Zoom to continue adding features to C++26. Thank you again to everyone reading this for your interest and support for C++ and its standardization.
February 12, 2024
Effective Concurrency: Live online course in April
I generally give one or two courses a year on C++ and related technologies. This year, on April 22-25, I’ll be giving a live online public course for four half-days, on the topic of high-performance low-latency coding in C++ — and the early registration discount is available for a few more days until this Thursday:
Effective Concurrency with Herb SutterHigh performance and low latency code, via concurrency and parallelism22-25th April 2024, from 14:00 – 18:00 CEST dailyParticipants in this intensive course will acquire the knowledge and skills required to write high-performance and low-latency code on today’s modern systems using modern C++. Presented by Alfasoft.
See the course link for details and a syllabus of topics that will be covered.
The times are intended to be friendly to the home time zones of attendees anywhere in EMEA and also to early risers in the Americas. If you live in a part of the world where these times can’t work for you, and you’d like another offering of the course that is friendlier to your home time zone, please email Alfasoft to let them know!
Because “high-performance low-latency” is kind of C++’s bailiwick, and because it’s my course, you’ll be unsurprised to learn that the topics and code focus on C++ and include coverage of modern C++17/20/23 features. But we are polyglots, after all… so don’t be overly shocked that I may sometimes show a few code examples in other popular languages, if only for comparison and to show how the other half lives.
November 11, 2023
Trip report: Autumn ISO C++ standards meeting (Kona, HI, USA)
Today, the ISO C++ committee completed its second meeting of C++26, held in Kona, HI, USA.
Our hosts, Standard C++ Foundation and WorldQuant, arranged for high-quality facilities for our six-day meeting from Monday through Saturday. We had over 170 attendees, about two-thirds in-person and the others remote via Zoom, formally representing 21 nations. Also, at each meeting we regularly have new attendees who have never attended before, and this time there were over a dozen new first-time attendees, mostly in-person; to all of them, once again welcome!
The committee currently has 23 active subgroups, most of which met in parallel tracks throughout the week. Some groups ran all week, and others ran for a few days or a part of a day and/or evening, depending on their workloads. You can find a brief summary of ISO procedures here.
This week’s meeting: Meeting #2 of C++26At the previous meeting in June, the committee adopted the first 40 proposed changes for C++26, including many that had been ready for a couple of meetings and were just waiting for the C++26 train to open to be adopted. For those highlights, see the previous trip report.
This time, the committee adopted the next set of features for C++26. It also made significant progress on other features that are now expected to be complete in time for C++26 — including contracts and reflection.
Here are some of the highlights…
Adopted for C++26: Core language changes/featuresThe core language adopted four papers, including P2662R3 “Pack indexing” by Corentin Jabot and Pablo Halpern officially adds support for using [idx] subscripting into variadic parameter packs. Here is an example from the paper that will now be legal:
template constexpr auto first_plus_last(T... values) -> T...[0] { return T...[0](values...[0] + values...[sizeof...(values)-1]);}int main() { static_assert( first_plus_last(1, 2, 10) == 11 );}For those interested in writing standards proposals, I would suggest looking at this and its two predecessors P1858 and P2632 as well written papers: The earlier papers delve into the motivating use cases, and this paper has a detailed treatment of other design alternatives considered and why this is the one chosen. Seeing only the end result of T...[0] would be easy to call “obvious” in hindsight, but it’s far from the only option and this paper’s analysis shows a thorough consideration of alternatives, including their effects on existing and future code and future language evolution.
Adopted for C++26: Standard library changes/featuresThe standard library adopted 19 papers, including the following…
The biggest, and probably this meeting’s award for “proposal being worked on the longest,” is P1673R13, “A free function linear algebra interface based on the BLAS” by Mark Hoemmen, Daisy Hollman, Christian Trott, Daniel Sunderland, Nevin Liber, Alicia Klinvex, Li-Ta Lo, Damien Lebrun-Grandie, Graham Lopez, Peter Caday, Sarah Knepper, Piotr Luszczek, and Timothy Costa, with the help of Bob Steagall, Guy Davidson, Andrew Lumsdaine, and Davis Herring. If you want to do efficient linear algebra, you don’t want to write your own code by hand; that would be slow. Instead, you want a library that is tuned for your target hardware architecture and ready for par_unseq vectorized algorithms, for blazing speed. This is that library. For detailed rationale, see in particular sections 5 “Why include dense linear algebra in the C++ Standard Library?” and 6 “Why base a C++ linear algebra library on the BLAS?”
P2905R2 “Runtime format strings” and P2918R2 “Runtime format strings II” by Victor Zverovich builds on the C++20 format library, which already supported compile-time format strings. Now with this pair of papers, we will have direct support for format strings not known at compile time and be able to opt out of compile-time format string checks.
P2546R5 “Debugging support” by René Ferdinand Rivera Morell, building on prior work by Isabella Muerte in P1279, adds std::breakpoint(), std::breakpoint_if_debugging(), and std::is_debugger_present(). This standardizes prior art already available in environments from Amazon Web Services to Unreal Engine and more, under a common standard API that gives the programmer full runtime control over breakpoints, including (quoting from the paper):
“allowing printing out extra output to help diagnose problems,executing extra test code,displaying an extra user interface to help in debugging, …… breaking when an infrequent non-critical condition is detected,allowing programmatic control with complex runtime sensitive conditions,breaking on user input to inspect context in interactive programs without needing to switch to the debugger application,and more.”I can immediately think of times I would have used this in the past month, and probably you can too.
Those are some of the “bigger” papers as highlights… there were 16 papers other adopted too, including more extensions and fixes for the C++26 language and standard library.
On track for targeting C++26: ContractsThe contracts subgroup, SG21, decided several long-open questions that needed to be answered to land contracts in C++26. Perhaps not the most important one, but the one that’s the most visible, is the contracts syntax: This week, SG21 approved pursuing P2961R0 “A natural syntax for contracts” by Jens Maurer and Timur Doumler as the syntax for C++26 contracts. The major visible change is that instead of writing contracts like this:
// previous draft syntaxint f(int i) [[pre: i >= 0]] [[post r: r > 0]]{ [[assert: i >= 0]] return i+1;}we’ll write them like this, changing “assert” to “contract_assert”… pretty much everyone would prefer “assert,” if only it were backward-compatible, but in this new syntax it would hit an incompatibility with the C assert macro:
// newly adopted syntaxint f(int i) pre (i >= 0) post (r: r > 0){ contract_assert (i >= 0); return i+1;}I already had a contracts implementation in my cppfront compiler, which used the previous [[ ]] syntax (because, when I have nothing clearly better, I try to follow syntax in existing/proposed C++). So, once P2961 was approved in the subgroup on Tuesday morning, I decided to take Tuesday afternoon to implement the change to this syntax, except that I kept the nice word “assert” because I can do that without a breaking change in my experimental alternate syntax. The work ended up taking not quite an hour, including to update the repo’s own code where I’m using contracts myself in the compiler and its unit tests. You can check out the diff in these | commits. My initial personal reaction, as an early contracts user, is that I like the result.
There are a handful of design questions still to decide, notably the semantics of implicit lambda capture, consteval, and multiple declarations. Six contracts telecons have been scheduled between now and the next meeting in March in Tokyo. The group is aiming to have a feature-complete proposal for Tokyo to forward to other groups for review.
Today when this progress was reported to the full committee, there was applause. As there should be, because this week’s progress increases the confidence that the feature is on track for C++26!
Note that “for C++26” doesn’t mean “that’s still three years away, maybe my kids can use it someday.” It means the feature has to be finished in just the next 18 months or so, and once it’s finished that unleashes implementations to be able to confidently go implement it. It’s quite possible we may see implementations available sooner, as we do with other popular in-demand draft standard features.
Speaking of major features that made great progress this meeting to be confidently on track for C++26…

The reflection subgroup, SG7, saw two experience reports from people actively using the prototype implementation of P2996 by Lock3 Software: P3010R0 “Using reflection to replace a metalanguage for generating JS bindings” by Dan Katz, and P2911R1 “Python bindings with value-based reflection” by Adam Lack and Jagrut Dave. As you can see from the titles, these were serious attempts to try out reflection for major use cases. Both experience reports supported P2996R1, so…
The group then voted unanimously to adopt P2996R1 “Reflection for C++26” by Wyatt Childers, Peter Dimov, Barry Revzin, Andrew Sutton, Faisal Vali, and Daveed Vandevoorde and forward it on to the main Evolution and Library Evolution subgroups targeting C++26. This is a “core” of static reflection that is useful enough to solve many important problems, while letting us also plan to continue building on it further post-C++26.
This is particularly exciting for me personally, because we desperately need reflection in C++, and based on this week’s progress now is the first time I’ve felt confident enough to mention a target ship vehicle for this super important feature.
Perhaps the most common example of reflection is “enum to string”, so here’s that example:
template requires std::is_enum_vconstexpr std::string enum_to_string(E value) { template for (constexpr auto e : std::meta::members_of(^E)) { if (value == [:e:]) { return std::string(std::meta::name_of(e)); } } return "";}Note that the above uses some of the new reflection syntax, but this is just the implementation… the new syntax stays encapsulated there. The code that uses enum_to_string gets to not know anything about reflection, and just use the function:
enum Color { red, green, blue };static_assert(enum_to_string(Color::red) == "red");static_assert(enum_to_string(Color(42)) == "");See the paper for much more detail, including more about enum-to-string in section 2.6.
Adding to the excitement, Edison Design Group noted that they expect to have an experimental implementation available on Godbolt Compiler Explorer by Christmas.
P2996 builds on the core of the original Reflection TS, and mainly changes the “top” and “bottom” layers that we knew we would likely change from the TS:
At the “top” or programming model layer, P2996 avoids having to do temp>::ming to use the API and lets us write something more like ordinary C++ code instead.And at the “bottom” implementation layer, it uses a value-based implementation which is more efficient to implement.This doesn’t mean the Reflection TS wasn’t useful; it was instrumental. Progress to this point would have been slower if we hadn’t been able to do the TS first, and we deeply appreciate all the work that went into that, as well as the new progress to move forward with P2996 as the reflection feature targeting C++26.
After the unanimous approval vote to forward this paper for C++26, there was a round of applause in the subgroup.
Then today, when this progress toward targeting C++26 was reported to the whole committee in the closing plenary session, the whole room was filled with sustained applause.
Other progressMany other subgroups continued to make progress during the week. Here are a few highlights…
SG1 (Concurrency) will be working on out-of-thin-air issues for relaxed atomics at a face-to-face meeting or telecon between meetings. They are still on track to move forward with std::execution and SIMD parallelism for C++26, and SIMD was reviewed in the Library Evolution (LEWG) main subgroup; these features, in the words of the subgroup chair, will make C++26 a huge release for the concurrency and parallelism group.
SG4 (Networking) continued working on updating the networking proposal for std::execution senders and receivers. There is a lot of work still to be done and it is not clear on whether networking will be on track for C++26.
SG9 (Ranges) set a list of features and priorities for ranges for C++26. There are papers that need authors, including ones that would be good “first papers” for new authors, so please reach out to the Ranges chair, Daisy Hollman, if you are interested in contributing toward a Ranges paper.
SG15 (Tooling) considered papers on improving modules to enable better tooling, and work toward the first C++ Ecosystem standard.
SG23 (safety) subgroup made further progress towards safety profiles for C++ as proposed by Bjarne Stroustrup, and adopted it as the near-term direction for safety in C++. The updated paper will be available in the next mailing in mid-December.
Library Evolution (LEWG) started setting a framework for policies for new C++ libraries. The group also made progress on a number of proposals targeting C++26, including std::hive, SIMD (vector unit parallelism), ranges extensions, and std::execution, and possibly some support for physical units, all of which made good progress.
Language Evolution (EWG) worked on improving/forwarding/rejecting many proposals, including a set of discussions about improving undefined behavior in conjunction with the C committee, including eight papers about undefined behavior in the preprocessor. The group also decided to pursue doing a full audit of “ill-formed, no diagnostic required” undefined behavior that compilers currently are not required to detect and diagnose. The plan for our next meeting in Tokyo is to spend a lot of time on reflection, and prepare for focusing on contracts.
Thank you to all the experts who worked all week in all the subgroups to achieve so much this week!
What’s nextOur next meeting will be in Tokyo, Japan in March hosted by Woven by Toyota.
Wrapping upThank you again to the over 170 experts who attended on-site and on-line at this week’s meeting, and the many more who participate in standardization through their national bodies!
But we’re not slowing down… we’ll continue to have subgroup Zoom meetings, and then in just four months from now we’ll be meeting again in person + Zoom to continue adding features to C++26. Thank you again to everyone reading this for your interest and support for C++ and its standardization.
October 9, 2023
My new CppCon talk is on YouTube: “Cooperative C++ Evolution – Toward a TypeScript for C++”
My Thursday CppCon talk is now online.
Note: There’s already a Reddit thread for it, so if you want to comment on the video I suggest you use that thread instead of creating a new one.
At CppCon 2022, I argued for why we should try to make C++ 10x simpler and 50x safer, and this update is an evolution of the update talk I gave at C++ Now in May, with additional news and demos.
The “Dart plan” and the “TypeScript plan”The back half of this talk clearly distinguishes between what I call the “Dart plan” and the “TypeScript plan” for aiming at a 10x improvement for an incumbent popular language. Both plans have value, but they have different priorities and therefore choose different constraints… most of all, they either embrace up-front the design constraint of perfect C++ interop and ecosystem compatibility, or they forgo it (forever; as I argue in the talk, it can never be achieved retroactively, except by starting over, because it’s a fundamental up-front constraint). No one else has tried the TypeScript plan for C++ yet, and I see value in trying it, and so that’s the plan I’m following for cppfront.
When people ask me “how is cppfront different from all the other projects trying to improve/replace C++?” my answer is “cppfront is on the TypeScript plan.” All the other past and present projects have been on the Dart plan, which again is a fine plan too, it just has different priorities and tradeoffs particularly around
full seamless interop compatibility with ISO Standard C++ code and libraries without any wrapping/thunking/marshaling, full ecosystem compatibility with all of today’s C++ compilers, IDEs, build systems, and tooling, andfull standards evolution support with ISO C++, including not creating incompatible features (e.g., a different concepts feature than C++20’s, a different modules system than C++20’s) and bringing all major new pieces to today’s ISO C++ evolution as also incremental proposals for today’s C++.See just the final 10 minutes of the talk to see what I mean — I demo’d syntax 2 “just working” with four different IDEs’ debuggers and visualizers, but I could also have demo’d that profilers just work, build systems just work, and so on.
I call my experimental syntax 2 (aka Cpp2) “still 100% pure C++” not only because cppfront translates it to 100% today’s C++ syntax (aka Cpp1), but because:
every syntax-2 type is an ordinary C++ type that ordinary existing C++ code can use, recognized by tools that know C++ types including IDE visualizers;every syntax-2 function is an ordinary C++ function that ordinary existing C++ code can use, recognized by tools that know C++ functions including debuggers to step into them;every syntax-2 object is an ordinary C++ object that ordinary existing C++ code can use;every syntax-2 feature can be (and has been) brought as a normal ISO C++ standards proposal to evolve today’s syntax, because Cpp2 embraces and follows today’s C++ standard and guidance and evolution instead of competing with them;and that’s because I want a way to keep writing 100% pure C++, just nicer.
“Nicer” means: 10x simpler by having more generality and consistency, better defaults, and less ceremony; and 50x safer by having 98% fewer vulnerabilities in the four areas of initialization safety (guaranteed in Cpp2), type safety (guaranteed in Cpp2), bounds safety (on by default in Cpp2), and lifetime safety (still to be implemented in cppfront is the C++ Core Guidelines Lifetime static analysis which I designed for Cpp2).
Cpp2 and cppfront don’t replace your C++ compilers. Cpp2 and cppfront work with all your existing C++ compilers (and build systems, profilers, debuggers, visualizers, custom in-house tools, test harnesses, and everything else in the established C++ ecosystem, from the big commercial public C++ products to your team’s internal bespoke C++ tools). If you’re already using GCC, Clang, and/or MSVC, keep using them, they all work fine. If you’re already using CMake or build2, or lldb or the Qt Creator debugger, or your favorite profiler or test framework, keep using them, it’s all still C++ that all C++ tools can understand. There’s no new ecosystem.
There are only two plans for 10x major improvement. (1-min clip) This is the fundamental difference with all the other attempts at a major improvement of today’s C++ I know of, which are all on the Dart plan — and those are great projects by really smart people and I hope we all learn from each other. But for my work I want to pursue the TypeScript plan, which I think is the only major evolution plan that can legitimately call itself “still 100% C++.” That’s important to me, because like I said at the very beginning of my talk last year (1-min clip), I want to encourage us to pursue major evolution that brings C++ itself forward and to double down on C++, not switch to something else — to aim for major C++ evolution directed to things that will make us better C++ programmers, not programmers of something else.
I’m spending time on this experiment first of all for myself, because C++ is the language that best lets me express the programs I need to write, so I want to keep writing real C++ types and real C++ functions and real C++ everything else… just nicer.
Thanks again to the over 120 people who have contributed issues and PRs to cppfront, and the many more who have provided thoughtful comments and feedback! I appreciate your help.
Herb Sutter's Blog
- Herb Sutter's profile
- 32 followers
