Trip report: Summer ISO C++ standards meeting (Rapperswil)

On Saturday June 9, the ISO C++ committee completed its summer meeting in beautiful Rapperswil, Switzerland, hosted with thanks by HSR Rapperswil, Zühlke, Netcetera, Bbv, SNV, Crealogix, Meeting C++, and BMW Car IT GmbH. We had some 140 people at the meeting, representing 11 national bodies. As usual, we met for six days Monday through Saturday, this time including all evenings.

Per our C++20 schedule, this was the second-last meeting for merging major language features into C++20. So we gave priority to the major proposals that might make C++20 or otherwise could make solid progress, and we deferred other proposals to be considered at a future meeting — not at all as a comment on the proposals, but just for lack of time. We expect to get to these soon once C++20 is well in hand.

Top news: Contracts adopted for C++20

Contracts (Gabriel Dos Reis, J. Daniel Garcia, John Lakos, Alisdair Meredith, Nathan Myers, Bjarne Stroustrup) was formally adopted for C++20.

Contracts allow preconditions, postconditions, and assertions to be expressed in code using a uniform syntax, with options to have different contract levels, custom violation handlers, and more.

Here are a few quick examples to get the flavor. Let’s start with perhaps the most familiar contract, assert:

void f() {
    int x = g();
    int y = h();
    [[assert: x+y > 0]]
}

“But wait,” someone might say, “C’s assert macro was good enough for my grandpappy, so shouldn’t it be good enough for me?” Never fear, you can still assert(x), but if you respell it as [[assert:x]] you get some benefits. For example:

  • You’re not relying on a macro (unlike C assert). Yes, this matters, because macros are outside the language and routinely cause problems when using language features. For example, this was demonstrated again just a few days ago on Twitter by Nico Josuttis (HT: Alisdair Meredith), who pointed out that assert(c==std::complex<float>{0,0}) does not compile; the reason is because macros don’t understand language commas, but [[assert: c==std::complex<float>{0,0}]] works just fine without any surprises.
  • You get to install your own violation handler and ship a release build with the option of turning on enforcement at run time.
  • You get to express audit to distinguish expensive checks to be run only when explicitly requested.
  • You get to express axiom contracts that are intended to never generate run-time code but are available to static analysis tools.
  • Finally, you will likely get better performance, because contracts should enable compilers to perform more optimizations, more easily, than expressing them using assertions.

But there’s more, because of course contracts are not just about assertions. They also include expects preconditions and ensures postconditions, which are part of the function declaration and so are visible at call sites:

double sqrt(double x) [[expects: x >= 0]];

void sort(vector<emp>& v) [[ensures audit: is_sorted(v)]];
    // could be expensive, check only when audit is requested

In addition to similar benefits as for assert, expects preconditions in particular deliver some enforcement benefits that are very desirable and difficult or impossible to get by hand:

  • Preconditions are usually enforced at the call site, which is what we want most of the time because a precondition violation always means a programming bug in the calling code.
  • But preconditions can also be enforced in the callee, which can sometimes be necessary for pragmatic reasons, such as when the function is invoked through an opaque function pointer.
  • Preconditions and postconditions that are known at the call site also give the optimizer more information to potentially make your code fast.

As a cheeky aside, if you noticed that I mentioned optimization several times, it’s for the usual reason: The simplest way to get C++ programmers to want a feature is to show that it can make their code faster, even if performance isn’t the only motivation or benefit.

Why contracts are a big deal, and related Rapperswil progress

In my opinion, contracts is the most impactful feature of C++20 so far, and arguably the most impactful feature we have added to C++ since C++11. That statement might surprise you, so let me elaborate why I think so.

Having first-class contracts support it is the first major “step 1” of reforming error handling in C++ and applying 30 years’ worth of learnings.

Step 2 is to (gradually) migrate std:: standard library precondition violations in particular from exceptions (or error codes) to contracts. The programming world now broadly recognizes that programming bugs (e.g., out-of-bounds access, null dereference, and in general all pre/post/assert-condition violations) cause a corrupted state that cannot be recovered from programmatically, and so they should never be reported to the calling code as exceptions or error codes that code could somehow handle. Over the past three meetings (Albuquerque through Rapperswil), the Library Evolution Working Group (LEWG) voted unanimously to pursue P0788R2 (Walter Brown) and relatedly in Rapperswil voted unanimously to pursue section 4.2 of P0709 (my paper), which includes pursuing a path of gradually migrating all standard library preconditions from exceptions toward contracts. (Note that in the near term, the idea is for implementations to be allowed, but not required, to use contracts. We are bringing the community forward gently here.)

Why is step 2 so important? Because it’s not just window dressing: Gradually switching precondition violations from exceptions to contracts promises to eventually remove a majority of all exceptions thrown by the standard library(!). This principle applies across programming languages; for examples, in Java and .NET some 90% of all exceptions are thrown for precondition violations (e.g., ArgumentNullException). Being able to eliminate a majority of all exceptions, which eventually enables many more functions to be noexcept, is a huge improvement for both correctness and performance:

  • Correctness: It eliminates a majority of the invisible control flow paths in our code. For example, over 20 years ago I wrote GotW #20 [Sutter 1997] that shows how today a 4-line function has 3 normal execution paths and 20 invisible exceptional execution paths; if we can eliminate a majority of the functions that can throw, we immediately remove a majority of the invisible possible execution paths in functions like this one, in all calling code.
  • Performance: More noexcept enables more optimization and faster code. (You knew that was coming, right?)

Once you change all preconditions (and postconditions and assertions) from exceptions to contracts, eliminating some of the largest categories of exceptions, one specific kind of exception dominates all others: bad_alloc. Which brings us to step 3…

Step 3 is to consider handling heap exhaustion (out-of-memory, OOM) differently from other errors. If in addition to not throwing on precondition violations we also do not throw on OOM, the vast majority of all C++ standard library functions can be noexcept. — Needless to say, this would be a huge change where we need to tread carefully and measure impact and high-fidelity compatibility in major real code bases, and we don’t want people to panic about it or think we’ve lost our minds: We are serious about bringing code forward gently after validating good adoptability and low impact long before this gets near an actual standard.

Nevertheless, we are also serious about improving this, and the fundamental change is simple and already fully supported in C++ today: In Rapperswil, LEWG also voted unanimously to pursue section 4.3 of P0709 (my paper) which proposes pursuing a path of gradually migrating all OOM from bad_alloc to new(nothrow)-like mechanisms. The initial contemplated step, definitely not for C++20, would be to change the default new_handler from throwing bad_alloc to calling terminate. That might sound like a big change, but it’s not, it’s already fully supported in C++ today because you can already change the new_handler to terminate today with a single line of code (std::set_new_handler([]{terminate();});), and this would just be changing the default and existing code that wants to keep the current behavior could still write simply the reverse single line of code (std::set_new_handler([]{throw std::bad_alloc();});) to get exactly the current behavior.

To repeat, this is a feature that will want a clear high-fidelity zero-breakage migration path, and we’re treating that compatibility seriously, even as we are also treating solving this problem seriously to modernize C++ error handling and move toward a mostly-noexcept world.

You can find a more detailed writeup in my new proposal P0709, particularly sections 1.1, 4.2, and 4.3. Again, P0709 is not for C++20, it is to illustrate a direction and potential path. The other parts of P0709 have not yet been reviewed by the full committee, so for now they should not be treated as anything more than a proposal, subject to much discussion and feedback over the coming several years.

Other new features approved for C++20

We adopted several other new features into the draft standard.

Feature test macros (Ville Voutilainen, Jonathan Wakely). This enables code to portably test whether a certain new C++ feature exists. “Why would I do that?” someone might ask. The primary and biggest benefit is they help your team to start to adopt new C++ features even before all your compilers support them; just write

#if /*new feature is present*/ // temporary
    nice clean modern code!    // <-- keep this long-term
#else                          // temporary
    do it the old way          // temporary
#endif                         // temporary

and eventually drop the #if test and the whole #else block as soon as all your compilers are up to date. This is so much better than today, where one of two things happens: (1) Teams often wait until all their compilers support a given new C++ feature before they start to use it, which slows down adopting the new features and getting their benefits at least on the compilers that do support it. Or, (2) teams roll their own nonstandard nonportable compiler-specific “approximate” feature tests (e.g., write their own macro for “I know this feature is available on version ## of MSVC and version ## of GCC” by hand).

We all agree we don’t like macros. However, we don’t yet have replacements for all uses of macros, including this one, and these standard macros are better than rolling your own nonstandard ones or, more likely, just not using new C++ features at all for a longer time.

Some experts still disagree, and we respect their views, but in my view these feature test macros are an important and pragmatic help to improve the speed of adoption of new standard C++ features.

Standard library concepts (Casey Carter, Eric Niebler). This is the first part of the Ranges TS to be merged into C++20 at an upcoming meeting, and contains the core concepts from the Ranges TS. It is also the first appearance of the concepts language feature in the standard library. Expect more to come for C++20 (see Ranges, below).

Class Types in Non-Type Template Parameters (Jeff Snyder, Louis Dionne). Yes, you can now have types other than int and char as non-type template parameters. For example, in addition to template<int Size>, you can now have things like template<fixed_string S> for a suitably defined class type. It turns out that this builds on the <=> spaceship comparison operator; and if you’re wondering why, it’s because we know the semantics of a defaulted <=> comparison, which is essential because the compiler has to perform comparisons to determine whether two template instantiations are the same.

Note: I did not have this benefit in mind at all when I proposed <=>. I think this is a great example where, when you let programmers express intent explicitly as with <=>, and provide useful defaults, you are inherently adding more reliable information to the source code and will reap additional benefits because you can now build on knowledge of that clear programmer intent.

explicit(bool) (Barry Revzin). This is conditional explicit, along the same lines as conditional noexcept. It lets library writers write explicit at a finer granularity, to turn off conversions where possible and feasible, without having to write two functions all the time.

Bit-casting object representations (JF Bastien). Header <bit> now lets you bit_cast. “But wait,” someone may be thinking, “don’t we already have reinterpret_cast?” Yes we do, and this is still a reinterpreting operation, but bit_cast has less unsafety and some additional flexibility: it ensures the sizes of the From and To types match, guarantees that they are both actually trivially copyable, and as a bonus makes the operation constexpr wherever possible.

Speaking of constexpr bit_cast, here are some more items in the “constexpr all the things!” department:

Other progress and decisions

Reflection TS is feature-complete: The Reflection TS was declared feature-complete and is being sent out for its main comment ballot over the summer. Note again that the TS’s current template metaprogramming-based syntax is just a placeholder; the feedback being requested is on the core “guts” of the design, and the committee already knows it intends to replace the surface syntax with a simpler programming model that uses ordinary compile-time code and not <>-style metaprogramming.

Parallelism TS2 is done: The second Parallelism TS is done! We completed ballot comment resolution, and approved the final TS for publication. This TS includes more execution policies, an exception_list type to communicate multiple parallel exceptions, and more parallel algorithms including wavefront, reductions, inductions, parallel for, and more. It also includes task_block support to enable writing custom parallel algorithms.

Graphics (io2d) is deferred: Many thanks to Michael McLaughlin especially, and to Guy Davidson, Michael Kazakov, and David Ludwig for their assistance with the design, specification, and implementation of this cross-platform library. This is a project that has been worked on for several years, and for the past two years has been primarily responding to committee tweak requests; unfortunately, although the committee requested a series of updates to the proposal that have been applied, at this meeting the committee decided that it does not have interest to pursue further work on graphics in any form at this time after all. However, the io2d project will continue, and be available on package managers (Conan, vcpkg), and we expect a renewed proposal in the medium term; in the meantime, watch Guy Davidson’s blog for news and updates.

Also, LEWG adopted P0921r2 as a statement of their direction for future C++ standard library evolution compatibility guarantees.

Updates on other major proposals

Here are other major items in progress. You’ll notice that the first six (6!) of them mention expectations for our next meeting this November in San Diego. Not all of those items will make C++20 in San Diego, but people are going to try. It’s not surprising that San Diego is going to be a busy meeting, though; that was expected, because it’s the last meeting to merge major features into C++20, and deadlines are famously motivational. — Just do not expect all of the following to make C++20, and I’m listing them in rough order starting with the most likely to make it in.

(very likely for C++20) Ranges: In my previous trip report I mentioned that the core concepts from the Ranges TS were expected to make C++20, but the rest of the Ranges TS would be “C++20 or C++23.” Since then we have made faster than expected progress, and it now looks like Ranges is “likely” to make C++20 in the next meeting or two. For those interested in details, in addition to all of the Ranges TS, also paper P0789 on Range Adaptors and Utilities have now progressed to detailed wording review and are targeting C++20. In sum, to quote Eric Niebler: “If you liked the Ranges TS, you’ll love C++20.”

(likely for C++20) Concepts: “convenience” notation for constrained templates: We already added the concepts core feature to C++20, and at this meeting we had further discussions on adding a convenience syntax to write constrained templates without resorting to the low-level “requires” keyword. The two major active proposals that received discussion were from Bjarne Stroustrup and from me. The good news is that the Evolution Working Group (EWG) liked both, which means that for the first time we have a proposal based on the TS syntax (Bjarne’s preference) that could get consensus to be approved!

The key people are continuing to work to come up with a merged proposal that might be adoptable for C++20 in November in San Diego, and I’m pleased to report that as of this post-meeting mailing we for the first time have a unified proposal that lists most of the previous authors of papers in this area as coauthors, you can find it here: P1141R0: “Yet another approach for constrained declarations.” I’m guardedly optimistic that we may have a winner here; we’ll know in San Diego. (I sometimes delay my trip report until the post-meeting mailing is available so that everyone can see the latest papers, and knowing that this new paper was coming was one reason I delayed this report.)

(maybe for C++20) Coroutines: EWG considered an alternative, then decided to go forward with the TS approach. That came up for full committee vote but fell just short and was not adopted for C++20; the proposers will continue to work on improving consensus over the summer by addressing remaining concerns and we expect coroutines to be proposed again for C++20 at our November meeting in San Diego.

Modules: For the first time, the committee saw a merged approach that both major proposers said satisfies their requirements; that announcement was met by applause in the room. The merged proposal aims to combine the “best of” the Modules TS and the Atom alternative proposal, and that direction was approved by EWG. EWG did not approve the poll to incorporate a subset of it into C++20 at this meeting; it is not yet clear whether part of the proposal can make C++20 but we are going to have an extra two-day meeting in September to help make progress and we expect it to be proposed again for C++20 at our November meeting in San Diego.

Executors: This is still not expected to be part of C++20, but key people have not given up and are trying to make it happen, and one never can tell. We are going to hold an extra two-day meeting in September to help make progress on Executors, and expect to have a lively discussion about options to merge all or parts of it into C++20 in November in San Diego.

Networking: This is pretty much ready except that it depends on Executors. Soon after Executors are ready for C++20, Networking is ready to slide in right behind it.

Clearly San Diego is going to be a busy meeting. But before then we have two extra design meetings on modules and executors to help improve their chances of progress; those will be co-located with CppCon in September, to take place near the CppCon site on the days just before the conference begins. On top of that, there will also be an extra library wording issues meeting in the Chicago area in August… all in all, it’ll be a full summer and fall before we even get to San Diego.

Additionally, SG12 had productive discussions about undefined behavior (including with participation from our sister ISO working group WG23, Programming Language Vulnerabilities), and SG15 had a second exploratory evening session focusing on package managers for C++.

What’s next

Here is a cheat-sheet summary of our current expectations for some of the major pieces of work. Note that, as always, this is an estimate only. The bolded parts are the major changes from last time, including that Ranges as a whole is looking very likely for C++20.

wg21-schedule-2018-06

And here is an updated snapshot of where we are on the timeline for C++20 and the TSes that are completed, in flight, or expected to begin:

wg21-timeline-2018-06

Thank you again to the approximately 140 experts who attended this meeting, and the many more who participate in standardization through their national bodies! Have a good spring… we look forward now to our next “extra” meetings in September (Bellevue, WA, USA) and the next regular WG21 meeting in November (San Diego, CA, USA).

Interview: On simplifying C++

I was also interviewed recently by Anastasia Kazakova for the CLion blog, and that interview is now live:

Toward a more powerful and simpler C++ with Herb Sutter

Topics include:

  • Concepts and modules (and coroutines) as the true hot topics right now
  • How my work on metaclasses was motivated and developed
  • Obligatory aside on operator<=> which grew out of the same work
  • Good and bad ways to learn from other languages and their experience
  • What are the next questions to be answered for metaclasses proposal
  • What has been the committee’s feedback so far
  • How can we expect to see reflection, compile-time code, injection, and metaclasses both progress in committee and get built into production compilers
  • How toolable are today’s C++11/14/17 features, and what about toolability for metaclasses

Interview with InfoQ: C++17, and beyond…

Last week I did an interview by email with InfoQ. It just went live:

C++17 is Here: Interview with Herb Sutter

Topics include:

  • What parts of C++17 should developers get most excited about?
  • Why didn’t concepts make it into C++17?
  • What will be the major focus areas for C++20?
  • What do you find interesting or inspiring about new languages like Rust, Swift, and Go?
  • Any new books coming? What’s your main focus today?

Update on October seminar in London

As I mentioned earlier, part of my fall schedule is to give a repeat of this spring’s sold-out seminar: “High-Performance and Low-Latency C++” (October 9-11, London, UK).

I am still getting mails about whether there are alternative/additional European dates for this seminar. Unfortunately, the answer is still no, but since I’m getting inquiries about it let me repeat that part of the earlier post:

On October 9-11, I’ll be in London giving a one-time repeat of “High-Performance and Low-Latency C++” (course details page). This is the same as the public course I gave in Stockholm [in April]; because that course sold out, and I was coming to Europe again for Qt World Summit anyway, we decided to do a single repeat that same week, this time in London.

Notes: (1) Some of you have emailed me asking if there will be other dates/cities, and the answer is no, sorry, I do seminars very rarely and this is the last one I have time to do for the foreseeable future. So if you are interested then this is the one to attend. (2) Some of you have also emailed me to ask whether the seminar will be recorded, and the answer is again no, sorry, the organizers are not set up for that. However, you can find all of my past Effective Concurrency writing (on which parts of this course are based) freely available via this blog, just search for that phrase or use the category tag — there’s a book’s worth of free material written by me in individual-article form.

So, if you’re interested, I hope you’ll be able to attend this October, and I look forward to seeing many of you there.

Metaclasses: Thoughts on generative C++

I’ve been working on an experimental new C++ language feature tentatively called “metaclasses” that aims to make C++ programming both more powerful and simpler. You can find out about it here:

  • Current proposal paper: P0707R1. I hope the first ten pages give a readable motivation and overview. (The best two pages to start with are 9 and 10, which probably means I need to reorder the paper…)
  • Initial intro talk video: ACCU 2017 (YouTube). This is the initial public presentation three months ago. Thank you to Roger Orr, Russel Winder, Julie Archer, and the other ACCU organizers for inviting me and for holding back the video until we could have the ISO C++ summer meeting about a week ago, so it could go live along with a report (herein) on the results of this feature’s first presentation to the ISO C++ committee. And special thanks to Ina and Arvid, the two audience volunteers who graciously agreed to come on-stage to participate in a live mini UX study. There’s a lot of subtle information in their nuanced reactions to the code examples; pay special attention when their responses are different or as their responses evolve.
  • “Incomplete and experimental” prototype compiler. The Clang-based prototype by Andrew Sutton is available as an online live compiler at cppx.godbolt.org, and as source at github.com/asutton/clang. It’s incomplete but can compile a number of the examples in the paper (see the paper for example code links). Thanks to Matt Godbolt for hosting it on godbolt.org!

Please see the paper and video to answer “what are metaclasses and why should I care?” If you’re the “show me code first, English later” kind of person, try the live compiler and these quick examples: interface, base_class, value (regular type), plain_struct (these links are also in the paper).

The rest of this post aims not to duplicate any information above, but to provide some context about the broader journey, and what I and others are attempting to accomplish.

A journey: Toward more powerful and simpler C++ programming

Phase 1: By using the existing language better

About five years ago, I started working on long-term effort toward making using C++ simpler and safer.

In the first phase, a small group of us—centered on Bjarne Stroustrup, Gabriel Dos Reis, Neil MacIntosh and Andrew Pardoe—pushed to see how far we could get with “C++ as it is” plus just a few well-chosen library-only extensions, with a particular goal of improving type and memory safety. Bjarne, Neil, and I first publicly reported on this effort in the two CppCon 2015 plenary sessions “Writing Good C++14” and “Writing Good C++14… By Default.” The results of that work so far have manifested as the C++ Core Guidelines and its support library GSL that adds a limited number of library types (e.g., span, now being standardized); and I led the Lifetime design in particular (available in the Guidelines /docs folder) which Neil and I and others continue to work on formalizing with the aim of sharing a “draft” static analysis spec later this year.

One of the goals of this phase was to answer the question: “How much progress can we make toward simplifying the existing C++ language with only a few key library extensions?” The answer as I see it turned out to be: “Some solid progress, but probably not a major simplification.” And so that answer led to phase two…

Phase 2: By evolving the language

Two years ago, I started to focus specifically on exploring ways that we might evolve the C++ language itself to make C++ programming both more powerful and simpler. The only way to accomplish both of those goals at the same time is by adding abstractions that let programmers directly express their intent—to elevate comments and documentation to testable code, and elevate coding patterns and idioms into compiler-checkable declarations. The work came up with several potential candidate features where judiciously adding some power to the language could simplify code dramatically.

Of those potential candidate features, metaclasses is the first major piece I picked to propose for ISO C++. [*] We presented it for the first time at the summer ISO C++ meeting earlier this month, and it received a warm reception. There was (rare) unanimous support for pursuing this kind of capability, but also some concern about how best to expose it and specific design change feedback the committee wants us to apply to improve the proposal. [**] We’ll work to include in a revision for the November standards meeting as we start the multi-year process of vetting and refining the proposal. So this is good progress, but note that it (only) means encouragement to continue the experiment and see where it leads; it’s far too early to talk about potential ship vehicles.

So do expect change: The proposal is still evolving, and it in turn assumes and builds on the static reflection proposal (P0578 et al.) and the compile-time programming proposal (P0633), both of which are actively evolving in their own right. Incidentally, one of the contributions of Andrew Sutton’s prototype metaclasses compiler is that it is implementing those other proposals too(!), since the metaclasses feature needs them. The aim is to keep the latest compiler and the latest P0707 paper in sync with each other and with those related proposals, but there will doubtless be occasional drift in between syncs.

What’s next

I’ll talk about metaclasses more in my upcoming CppCon 2017 talk this September, and Andrew Sutton will also be giving two CppCon talks about metaclasses—one about implementing them in Clang, and one about using them for a real project.

This is just the beginning, and we’ll see whether it all pans out and leads somewhere, but I hope you enjoy this exploration and I look forward to talking with many of you about it at CppCon this September.

 

———

Notes

[*] I actually brought a smaller piece from this same work to the committee at the previous meeting, the winter meeting in Kona: P0515 (consistent comparisons), which proposes adding the three-way <=> comparison operator. P0515 is only about a minor feature, and not one of the most important things that can help improve C++, so normally I wouldn’t have picked that piece to contribute first; but the committee was already continuing to actively discuss comparisons, so I cherry-picked it from my design work and contributed it since I had the design in my pocket anyway. Happily the committee liked what they saw and both EWG and LEWG accepted it, and it is now progressing well and on track to hopefully be voted into draft C++20 in the next meeting or two. Thanks to Jens Maurer and Walter Brown for the heavy lifting of writing the core language and library standardese wording, respectively, for that P0515 proposal.

[**] The committee’s design feedback was primarily about how to wrap up the transformation code: Instead of putting it inside a new “meta” class-like abstraction, how about wrapping the same code inside a compile-time function-like abstraction that takes an input meta::type parameter and returns a generated meta::type return value? This doesn’t affect the proposal’s basic engine, just the shape of its steering wheel—for example, we could change the first line of each example metaclass definition from the class-like syntax

$class interface {
    constexpr {
        // … basically same code …
    }
};

to the decorator-function-like syntax

meta::type interface(const meta::type source) {
    // … basically same code …
};

where the latter has the advantage that it’s easy to see that we’re reading one type and generating another type. Interestingly, I think this dovetails with the mini UX study in the video where most of the difficulty the UX participants seemed to encounter was in understanding the $class syntax, not the metaclass bodies and not later using the metaclasses to author new types.

But we’ll explore this and other options and validate/invalidate it with more experiments… and feel free to express your thoughts in the comments if you like one of these styles better, or perhaps another variation.

Trip report: Summer ISO C++ standards meeting (Toronto)

No, we didn't meet at city hall, but this shot was taken from the primary hotel which was across the street from city hall. Also, this building appears in Star Trek: http://spacing.ca/toronto/2013/10/01/star-trek-toronto-city-hall/[This post will be updated with additional details as mentioned in the comments section at bottom.]

A few minutes ago, the ISO C++ committee completed its summer meeting in Toronto, Ontario, Canada. We had some 120 people at the meeting, representing nine national bodies. As usual, we met for six days Monday through Saturday, including several evenings.

The following are some highlights of what we achieved this week. You can find a brief summary of ISO procedures here. The main things to note are:

  • “IS” means “international standard.” In our case, it’s the core C++ standard itself. Think of this as “trunk.”
  • “TS” means “technical specification,” a document separate from the main standard where we can gain experience with new features before putting them into the IS. We have several of these, summarized on the status page. Think of these as “beta branches.”

Note: As I reported in my previous trip report for the winter meeting (Kona 2017), we have already completed our work on C++17, which is now still going through its final ISO approval steps. Nothing we did this week affects C++17, but we did begin work on C++20…

First meeting for C++20

This was the first meeting where we could vote changes into Draft C++20. And we did!

First, the Concepts TS was merged into draft C++20. Yes, Concepts are back in the draft international standard and better than C++0x, which makes the famous concepts feature (principally driven by Bjarne Stroustrup, Gabriel Dos Reis, and Andrew Sutton) the first major language feature voted into draft C++20. Recall that Concepts was published as a separate TS two years ago, and available in GCC; today we voted to adopt nearly of it, except only the “introducer syntax” and “terse/natural syntax” for now because that syntax still has a handful of remaining issues that don’t have consensus, but it’s close and Evolution also voted unanimously to aggressively pursue adding the terse syntax as soon as possible once those design questions can be addressed. A few specific Concepts changes were also approved along with the merge, notably removing the need to write “bool” and removing function concepts until we see a need to overload concepts.

Here are some other features that were added to C++20 at this meeting. Note: These links currently find the most recent pre-meeting papers and so may not reflect the exact wording adopted at the meeting, but the links will light up to the post-meeting versions of the papers that were actually adopted as soon as those are available in the post-meeting mailing about three weeks from now.

One TS sent for its ISO ballot, three TSes completed to be published

We also spent quite a bit of the week working on three TSes that completed their review ballots, and sending out one more: The Modules TS is sent out for its comment and approval (PDTS) ballot. And the Coroutines TS, Networking TS, and Ranges TS are all done, as the groups worked hard to process and address all the comments from their ballots and we are sending them out for final publication. – It’s not every meeting that we publish three specifications! Some of them would have been handled at our last meeting, but we were busy finishing C++17 so they stacked up for this meeting.

Thank you very much again to all the volunteers who helped progress our proposals, send out our PDTSes, address our ballot comments and publish three (3) TSes, and get the C++20 cycle off to a roaring start.

Other progress

We considered merging one other published TS, the Concurrency TS. The feeling was that its three major features were in different stages of readiness, and some are advancing toward bring merged into C++20, possibly at our next meeting:

  • atomic_shared_ptr<T> is on track to be merged into C++20 with changes, in detailed standardese wording review and expected to be put up for approval at our next meeting. Interestingly, some of the changes are to make it more like the original design I proposed, including to name it atomic<shared_ptr<T>>.
  • Latches are also approved, essentially as-is, and the feature is in wording review for the next meeting.
  • Barriers are also potentially on track for C++20 but SG1 is still discussing open design problems. Its design can be expected to change substantially from the TS version.
  • Some minor pieces of the future extensions are moving ahead, but the extension has several unresolved design issues including to coordinate with the (we hope soon-coming) executors design.

Other items making progress for possible consideration to be adopted in the fall meeting:

The Library Evolution group has started discussing at how to integrate modules and contracts into the standard library. They expect to start integrating concepts next meeting, which is a big benefit of getting a major feature merged early in the C++20 cycle. They are also actively working on Unicode support, several new containers, and a date library, among other things.

We also continued incubating other work. In particular, the Reflection study group had presentations, and gave direction and feedback, on a few additions to the static reflection proposal that is already progressing in the main subgroups, the compile-time programming proposal, and my new metaclasses paper. (I’ll post a separate report on the metaclasses part soon, probably in the next week or so, with a link to the ACCU video.)

What’s next

In my trip report last fall, two meetings ago, I wrote: “Then, once C++17 ships next year and possibly as soon as our July meeting, I expect we’ll start looking at merging more of the TS ‘beta branches’ into the C++ ‘trunk.’”

Well, that’s exactly what happened: We did finish C++17 at the next meeting, and now at the meeting after that we did merge our first major TS into the C++ trunk.

Here’s an updated snapshot of our status (the latest is always on the isocpp.org/std/status page):

wg21-timeline-2017-07b

Thank you again to the 120 experts in Toronto this week, and the many more who participate in standardization through their national bodies! Have a good summer – and see you at CppCon!

This fall: ACAT & CppCon (Seattle), High-Performance/Low-Latency C++ (London), Qt World Summit (Berlin)

[6/26: Updated to add ACAT]

I can’t remember the last time I’ve gone to Europe twice in one year, but this is the year… up first are ACAT in August and CppCon in September, then a week later in early October I’ll be heading to London to give a single repeat of the three-day High-Performance and Low Latency C++ course, in the same week that I’ll be in Europe already to give a keynote at Qt World Summit in Berlin.

Aug 21-25: ACAT

This year I’ll be giving a keynote at ACAT (topic and day tbd). Unfortunately I cannot be there in person due to conflicts, but the organizers are graciously making arrangements for a remote presentation.

Mon-Fri Sep 25-29*: CppCon (Seattle)

I’ll be giving a brand-new talk at CppCon. If you haven’t registered yet for CppCon but are thinking of coming, note that the Early Bird discount ends on July 7, the end of next week.

* Those are the dates of the 5-day core conference, but technically the full dates are Sep 23 – Oct 1 because CppCon has grown into, somewhat incredibly, a nine-day event this year. How it happened: Last year, we added two days of optional pre-conference tutorials on the weekend before the conference as an experiment; those were so successful that this year there are tutorials on both weekends, before and after the conference, again as an experiment… but I know that at least a few of you have already signed up for all 9 days (wow).

Mon-Wed Oct 9-11: High-Performance and Low-Latency C++ (London)

On October 9-11, I’ll be in London giving a one-time repeat of “High-Performance and Low-Latency C++” (course details page). This is the same as the public course I gave in Stockholm two months ago; because that course sold out, and I was coming to Europe again for Qt World Summit anyway, we decided to do a single repeat that same week, this time in London.

Notes: (1) Some of you have emailed me asking if there will be other dates/cities, and the answer is no, sorry, I do seminars very rarely and this is the last one I have time to do for the foreseeable future. So if you are interested then this is the one to attend. (2) Some of you have also emailed me to ask whether the seminar will be recorded, and the answer is again no, sorry, the organizers are not set up for that. However, you can find all of my past Effective Concurrency writing (on which parts of this course are based) freely available via this blog, just search for that phrase or use the category tag — there’s a book’s worth of free material written by me in individual-article form.

Thu Oct 12: Qt World Summit (Berlin)

The next day, I’ll be in Berlin giving one of the keynotes at Qt World Summit. I’m not sure yet whether it’ll be the closing keynote; for more details, please check their conference schedule once it’s posted.

I look forward to seeing many of you at these events.

This spring: High-Performance and Low-Latency C++ (Stockholm) and ACCU (Bristol)

I don’t get to Europe very often apart from ISO C++ standards meetings, but this spring I’ve been able to accept invitations for two English-language European events in the last week of April. If you’re interested in attending, please check out the links, and I look forward to meeting and re-meeting many of you there.

Tue-Thu Apr 25-27: High-Performance and Low-Latency C++ (Stockholm)

On April 25-27, I’ll be in Stockholm (Kista) giving a three-day seminar on “High-Performance and Low-Latency C++.” This contains updated and new material that reflects the latest C++ standards and compilers, with a focus to using modern C++11/14/17 effectively on modern hardware and memory architectures.

Note that the class size is limited to about 100, so that I’ll be able to interact with most attendees directly. Registration just opened recently and hasn’t been widely publicized yet, but today I was told that it’s already over 1/3 full. So if you or your colleagues might be interested in attending, please check out the link above; for group registrations, please contact Alfasoft directly.

Here is the summary, below; for a more detailed topic breakdown see the link above.

Description

Performance and efficiency are C++’s bread and butter, and they matter more than ever on modern hardware: In processors, single-threaded performance improvements are slowing down (unless your code is parallel); in Internet of Things, we are often asked to do more work with less hardware; and in cloud computing, processor/hardware time is often the major component of cost and so making code twice as efficient often means saving close to half the processing cost. Today, getting the highest performance and the lowest latency on modern hardware often means being aware of the hardware in ways that most other programming languages can’t – from hardware caches where simply arranging our data in the right order can give 50x speedups with otherwise identical code, to hardware parallelism where using parallel algorithms turns on high-performance parallel and vector processor hardware that otherwise sits idle.

Additionally, low latency increasingly matters at all scales: In user interfaces, low latency means responsive apps and productive users without the dreaded “wait…” donut; in financial trading, low latency regularly saves large amounts of cash; in embedded real-time systems, low latency is crucial to meeting deadlines and can even save lives. Today, this makes concurrency more important than ever, because it delivers two things: It hides latencies we have to deal with and cannot remove, from disk I/O latency to speed-of-light network latency; and it makes our code responsive by not introducing needless latencies of our own even when we’re not hiding someone else’s latency.

Goal

This intensive three day course will provide developers with the knowledge and skills required to write high-performance and low-latency code on today’s modern systems using modern C++11/14/17. During the training you’ll learn how to get the highest performance and the lowest latency on modern hardware in ways that are unique to C++, including how to arrange data to use hardware caches effectively, and how to use standard and your own custom-written parallel algorithms to harness high-performance parallel and vector processor hardware to compute results faster. You’ll also learn how to manage latency for responsive apps and for real-time systems, and techniques to hide the underlying latencies we have to deal with and cannot remove such as disk and network latency, and to make your own code responsive by not introducing needless latencies in your own code.

Sat Apr 29: ACCU closing keynote (Bristol)

Next, I’ll be heading to Bristol to catch the end of the ACCU 2017 conference, and give the closing talk on “Something(s) New in C++.” No, the title is not intentionally a tease; it’s just that I have several topics available, and I won’t be sure until about a month before the event which will be the best one to speak about. Here is the current abstract:

By the time the ACCU 2017 conference begins, C++17 is expected to be technically complete and in its final approval ballot. What comes next? Will C++ continue growing forever? Can C++ code be simplified? This is a brand-new talk of material I’ve never given before, in which I’ll present one (or more) of three proposals I’m personally working on to further improve C++ post-C++17. All follow a common theme – adding a strategic language and/or library feature to C++ that leads to significant, and sometimes dramatic, simplification of real-world C++ code. I’ll pick which one (or more) of those topics to present sometime in March.

What I can say is that, whichever topic it ends up being, it’ll be something you haven’t seen before that’s forward-looking and aimed directly toward making C++ code simpler and easier… and of course without compromising C++’s model of efficient machine-near abstraction.

I look forward to seeing many of you in Europe this spring.

Trip report: Summer ISO C++ standards meeting (Oulu)

On June 25, the ISO C++ committee completed its summer meeting in Oulu, Finland, hosted by Symbio and the Finnish national body.

We again had some 100 experts officially representing nine national bodies. As usual, we met for six days Monday through Saturday, and around the clock from 8:30am till 11pm most days – evening sessions regularly went a little later than the usual 10pm because it was Midsummer and there was literally no full night all week long at that short distance from the Arctic Circle, and people commonly did a double take when they looked at their watches and were surprised to find that it was already nearly midnight.

Here’s a summary of what happened, with some details about the current ISO C++ process so you can see just how the work is progressing and getting released. I’ve tried to add some links to the relevant feature design papers, or to the papers that summarize what was done which in turn usually carry more links to the design papers.

C++17 is feature-complete, enters review period

The big news is that C++ is feature-complete, and on time! We added several more features to the C++17 working paper (see next section), then approved the result to be sent out this summer for its major ISO international comment ballot, which is the Committee Draft or “CD” ballot.

Between now and our November meeting, national bodies around the world will be reviewing the draft and reporting any concerns about feature design details and wording correctness or consistency. Then for probably the next two meetings we’ll be addressing every national body comment and recording its resolution, as well as continuing to process our own known issues lists to fine-tune the text of the standard. That usually takes two meetings, and if that’s the case again this time then we’ll be putting the finishing touches on C++17 in our November and March meetings and then, we hope, sending C++17 out for its possibly-final ballot in the spring. If we need an extra meeting, then that would extend to the July meeting next year and the possibly-final ballot in late summer.

So C++17 is and tracking to ship on schedule next year. In my March trip report, I mentioned that after completing C++11 we switched to a “train model” where we have been shipping the standard consistently every three years. So far, we have been running the trains on time: C++14 was actually the first C++ standard ever that shipped when expected, and now C++17 is on track to do it again. This is excellent news for the community because it enables implementers to track the standard closely, whereas in previous releases they often held back from implementing new features aggressively because with an open-ended schedule the committee could (and did) change its mind again about the design of some feature before the standard actually shipped. The ISO C++ committee is now sticking to a high quality bar, voting features in when they’re stable and releasing on time, which removes uncertainty and is a major reason why compilers are more in sync than ever before: After C++98 shipped, it took 5 years before we saw the first complete conforming compiler that implemented all language features (modulo bugs of course); after C++11 shipped, it took 3 years; when C++14 shipped, it took months. Now, many C++17 features are already available in major compilers, and I wouldn’t be surprised if C++17 repeated C++14’s synchronization with the community so that we see at least one major implementation that has all C++17 features in the same year that C++17 is published. This is great news for the community, because it means we have to play less of the “which compilers actually implement which features” game; true, we still need to deal with older compilers, and some compilers are still not as quick as others to ship the latest features, but all of the major compilers’ current releases are in closer sync with the standard than they’ve ever been before and even the delta between them continues to shrink, which is good news for all C++ users.

Note: Last time I mentioned that there was some thought of moving to a two-year cadence after C++17, but for now we’re staying with three years, so the next standard after C++17 will be C++20.

More features added to C++17

At this meeting, we added several more features into C++17; you can find a good summary of those features in Bryce Lelbach’s Reddit post. Again, note that these are just the ones we added at this meeting; the complete list of C++17 features is longer. For example, see my March trip report for what was added at the spring meeting.

Language features

Here are some of the more noticeable language features we added to C++17 in Oulu. I’ll merge from Bryce’s nice list (thanks Bryce!), my own comments in the previous trip report, and some new comments and examples:

Dynamic memory allocation for over-aligned data: Extending the C++11 alignof/alignas for heap allocated memory control.

Template argument deduction for constructors, so that you can write just pair p(2, 4.5); instead of pair<int,double> p(2, 4.5); or auto p = make_pair(2, 4.5);. This is pretty sweet, including that it obsoletes many “make” helpers.

template <auto>: Recall that templates can take “non-type parameters,” or ordinary compile-time values; a familiar example is std::array<widget,10> which is an array of 10 widget objects, passing 10 as a compile-time number. Well, as of C++11 we allow “auto”matically deducing the type of local variables:

auto i = 10;           // deduces int

and in the Concepts TS we allow “auto”matically deducing the type of parameters:

void f(auto value) { } // same as template <class T> void f(T value);

f(10);                 // deduces int

Now, with the template<auto> extension, C++17 will additionally allow the same to happen when you pass a value as a template parameter, which is just another place you can pass a value:

template <auto value> void f() { }

f<10>();               // deduces int

Guaranteed copy elision: When you call a function that returns an object by value, and you use the copy to initialize a local variable, the language has always said that you copy (or move) twice. You may know that, since forever, C++ has also added, “but by the way, the compiler is allowed to elide (disappear) the extra copy.” With guaranteed copy elision, in many cases the C++17 language now says you copy (or move) once; that is, compiler is now required not to perform an extra copy or move, so that copy elision is no longer an optimization but a guaranteed language feature.

Richard Smith, the proposal author, provided the following additional notes and examples that show how the copy elision guarantee depends on what happens inside the function. In some cases, such as when the function returns a temporary of the right type, the new rules guarantee that zero copies will be performed, and the return type is not even required to be copyable or movable any more:

T f() {
  return T{}; // no copy here (C++17)
}

T x = f();    // no copy here either (C++17)

In other cases, where the named return value optimization (NRVO) would apply today, there is one copy and the compiler may elide the copy, but is not guaranteed to do so because there are cases where that could not be guaranteed:

T g() {
  T t;
  return t;   // one copy, can be elided but elision is not guaranteed
}

T y = g();    // no copy here (C++17)

And if the function returns something that really requires a copy, such as returning a reference parameter, you get exactly one copy:

T h(T &t) {
  return t;   // one guaranteed copy (by necessity)
}

T z = h(x);   // no copy here (C++17)

Order of expression evaluation guarantees: This removes portability and usability bugs. In a nutshell, a number of code examples that you thought worked, now actually do work. In particular, this solves the long-standing f(new T, new T) bug that I wrote about nearly 20 years ago, fixes some examples in published books, and makes the brand-new future<T>::then chaining actually work correctly.

Inline variablesThis feature makes it easier to define global variables (that’s the bad news) correctly (that’s the good news), including in header files. The net effect is that some code people already write in practice, but shouldn’t have because it had subtle pitfalls, now works.

if constexpr: This is a very powerful feature that allows branches that are evaluated at compile time. Note that this is a disciplined compile-time “if”, not just text substitution; the code in a false branch needs to be syntactically well-formed, but doesn’t need to be semantically valid.

This lets you express some pretty powerful stuff, including that a function template can write all the special cases of its algorithm right within its body (e.g., a fast algorithm for random-access iterators, and a fallback for less powerful iterators), without writing a set of template specializations.

It also works very nicely with C++14’s “auto” return type deduction for inline functions: It’s perfectly fine for two mutually exclusive if constexpr branches to return unrelated types since only one of the branches can be taken for a given set of inputs, and the correct return type will be deduced. Of course, within the same if constexpr branch the return types have to be compatible according to the current rules. In fact, we’ll see an example of this in the next topic…

Structured bindings: This allows taking a value that contains multiple elements, such as a tuple or a struct, and binding convenient names to the individual elements – much like std::tie, except without having to have variables of the correct type already available. I was pleasantly surprised to see this one make it into C++17 even though it came in late in the cycle. Here’s a simple example of what it enables:

tuple<T1,T2,T3> f();
auto [x,y,z] = f(); // types are: T1, T2, T3

map<int,string> mymap;
auto [iter, success] = mymap.insert(value); // types are: iterator, bool

struct mystruct { int i; string s; double d; };
mystruct s = { 1, “xyzzy”s, 3.14 };
auto [x,y,z] = s; // types are: int, string, double

What if you want to add structured bindings for your own type that isn’t a struct or a tuple? I’m glad you asked, because it’s an excuse to also show off also how you can use if constexpr. Let’s say you’re the author of a type S:

class S {
   int i;
   char c[27];
   double d;
public:
   // ...
};

Now you want to allow structured bindings for your type S, and for extra marks you don’t want to bind directly to the private variables but perhaps want member c to be bound as a string_view (also adopted for C++17; see below). Here’s how do add this ability; it’s a few lines, but you only have to do it once for all users of type S:

// 1. Add tuple_size and tuple_element support
namespace std {
   template<> struct tuple_element<0,S> { using type = int; };
   template<> struct tuple_element<1,S> { using type = string_view; };
   template<> struct tuple_element<2,S> { using type = double; };
   template<> struct tuple_size<S>: public integral_constant<size_t,3> {};
}

// 2. Now add get<> support (using C++17, because why not; it’s better
// than =delete’ing the primary get<> template and adding specializations)
template<int I>
auto get(const S&) {
   if      constexpr(I == 0) return x.i;
   else if constexpr(I == 1) return string_view{x.c}; }
   else if constexpr(I == 2) return x.d;
}

Now all users of S can write code like this:

S f();  // some function that returns an S

auto [ n, s, val ] = f(); // types are int, std::string_view, and double

if (init; condition) and switch (init; condition): Just like the venerable for (int i = 0; /*…*/) loop has always allowed declaring a variable (in that example, i) that exists for the scope of the loop, we will now be able to do the same for if and switch without having to resort to today’s workaround of declaring the variable before the if or switch and then wrapping it up in { } to restrict its scope. Here’s an example of the new cleaner syntax, which allows more tightly-scoped variables:

map<int,string> mymap;

if (auto result = mymap.insert(value); result.second) {
    // insert succeeded, and result is valid for this block
    use(result.first);  // ok
    // ...
} // result is destroyed here

In fact, you might have noticed that I used a similar example for both structured bindings and for if/switch initialization. It took Reddit about 30 minutes to discover that they’re great together, like peanut butter and jelly:

// better together: structured bindings + if initializer

if (auto [iter, succeeded] = mymap.insert(value); succeeded) {
    use(iter);  // ok
    // ...
} // iter and succeeded are destroyed here

Two language features that didn’t make it (yet)

Of the new language features I mentioned last time, only two didn’t make it into C++17:

  • operator. (dot) to allow smart references (in parallel with smart pointers) and much more. During final core language wording review, the authors discovered a problem that couldn’t be fixed in real time at this meeting, and was pulled back while the authors fix the proposal. This proposal is still active and is expected to come back with a fix to that problem very soon, possibly as soon as in the next week or two for the post-meeting mailing; I’m hearing some rumblings that national bodies might mention this in their summer ballot comments, so we might see it again during C++17 ballot resolution, else I’d expect it to be one of the first things added to the draft standard once C++17 ships.
  • Defaulted comparisons, to generate ==, !=, <, <=, >, >= for types that don’t write them by hand. The current version of the proposal is opt-out, and would generate comparisons for existing types. When the proposal got to the full committee, we discovered that the committee didn’t have consensus to approve the paper’s opt-out model; a number of people spoke up for an opt-in model instead. This proposal might eventually come back but probably not soon.

Standard library features

Here are some of the library features that made it into C++17 at this meeting:

variant<>: Don’t use raw unions any more. This addition completes the trifecta of std::any and std::optional (which were already added to C++17). The new std::variant is a type-safe union; for more background see also my fall meeting trip report. Here’s an example adapted from the paper that shows how you can use it:

variant<int, float, string> v, w;
v = “xyzzy”;         // now v contains a string
v = 12;              // now v contains an int

int i = get<int>(v); // ok, because it contains an int

w = get<int>(v);     // ok, assign to another variant
w = get<0>(v);       // same effect as the previous line
w = v;               // same effect as the previous line

get<double>(v);      // compile-time error: v can’t contain a double
get<3>(v);           // compile-time error: v doesn’t have 4 types

try {
  get<float>(w);     // will throw: w contains an int, not a float
}
catch (bad_variant_access&) {}

Moving nodes between map<>, unordered_map<>, set<>, and unordered_set<>: You will now be able to directly move internal nodes from one node-based container directly into another container of the same type (differing at most in the comparator template parameter), either one node at a time or the whole container. Why is that important? Because it guarantees no memory allocation overhead, no copying of keys or values, and even no exceptions if the container’s comparison function doesn’t throw. The mechanics are provided by new functions .extract and .move, and corresponding new .insert overloads. Here’s an example adapted from the paper:

map<int, string> src {{1,”one”}, {2,”two”}, {3,”buckle my shoe”}};
map<int, string> dst {{3,”three”}};

dst.insert(src.extract(src.find(1))); // iterator version
dst.insert(src.extract(2));           // key type version
auto r = dst.insert(src.extract(3));  // key type version
    // note: this last one will fail because dst already contains 3;
    // the node is owned by r, the returned struct

// At this point we have the following state:
//   src == {}
//   dst == {{1,“one”}, {2,“two”}, {3,“three”}}
//   r.position == dst.begin() + 2
//   r.inserted == false
//   r.node == {3,“buckle my shoe”}

// We can go back and retry the failed insert with a different key:
r.node.key() = 4;                      // use a non-conflicting value
dst.insert(r.position, std::move(r.node));  // now succeeds

Extended memory management tools for in-place construction and destruction: These include destroy(_at|_n), uninitialized_move(_n), uninitialized_value_construct(_n), and uninitialized_default_construct(_n).

In case you missed it: string_view also in C++17

C++17 also contains a number of other useful features. I’ve mentioned these before, including “small” but widely-used features like optional and any, right up to Parallel STL. But let me just take a moment to remark again on the wonderfulness of string_view, which is a non-owning view of a contiguous string owned by someone else.

If you have a const string& parameter, consider just changing it to string_view. As Mark Isaacson mentioned in his NDC talk earlier this month, it’s pretty rare that you can get a performance boost by just doing a global search-and-replace, but Mark points out you can pretty much do that by globally replacing const string& with string_view (with one exception noted in the next paragraph). Why is this often more efficient? In particular, when the caller passes something like a string literal as an argument, if your function takes it via a const string& parameter that means the caller has to convert the string literal to a temporary string object, which typically incurs a heap allocation and deallocation, whereas passing it to a string_view incurs no allocation overhead at all.

However, beware one potential pitfall, especially until more of the world has migrated to string_view: If your function f(/*some string*/ x) internally calls one or more other functions that still take a string& (either const or non-const), then let your function f continue to take x by const string& and don’t change it to string_view. The reason is that if f is called with an actual string object, then f(const string& x) can pass it along painlessly by reference, whereas f(string_view x) would avoid a copy when entering f but would need to create a new string internally just to pass it along to the other function that needs a string. Bottom line: If you know your function needs to call other functions that you don’t control and that take (possibly const) string&, then you should probably leave your function taking const string& too.

C++17: Recognizably new

C++17 will pervasively change the way we write C++ code, just as C++11 did. As these and other new features become available, we’re going to see new code using structured bindings, if/switch scope variables, string_view, optional, any, variant, Parallel STL, and more all over the place.

Here’s my personal litmus test for whether we’ve changed the way people program: Just as you can take a look at a screenful of code and tell that it’s C++11 (not C++98), if you can look at a screenful of code and tell that it’s C++17, then we’ve changed the way we program C++. I think C++17 will meet that bar.

Here’s a little “C++17 demo” put together by committee member Thomas Köppe, who is the author of the if/switch initializer proposal. It shows off a few of the features that will soon be available as part of C++17, and how they work together. Note this uses some other new C++17 features I didn’t specifically mention. I’ll let the comments speak for themselves; thanks, Thomas, for providing this demo.

unordered_map<string, unique_ptr<Foo>> items;
vector<unique_ptr<Foo>> standby;

// Desired semantics of f: If there is currently no item 'id', install
// 'foo' as item 'id'. Otherwise, put 'foo' on the standby list for later.

//------------------------------------------------
// Before C++17: 7 lines + 4 pitfalls
//
void f(string id, unique_ptr<Foo> foo) {
   auto it = items.find(id);
   if (it == items.end()) {
      auto p = items.emplace(move(id), move(foo));
      p.first->second->launch();
   } else {
      standby.push_back(move(foo));
      standby.back()->wait_for_notification();
   }

   // Notes:  
   // * Variable 'id' can no longer be used (moved-from); or...  
   // * ...would need to pass by 'const string& id' and force copying.
   // * Map lookup performed twice. Ordered map could use lower_bound +
   //   hint, but unordered map cannot.  
   // * (Cannot emplace unconditionally, because it might destroy *foo.)
}

//------------------------------------------------
// With C++17: 4 lines + none of those pitfalls
//
void f(string_view id, unique_ptr<Foo> foo) {
   if (auto [pos, inserted] = items.try_emplace(id, move(foo)); inserted){
      pos->second->launch();
   } else {
      standby.emplace_back(move(foo))->wait_for_notification();
   }
}

Other progress

Because this time our focus was on completing C++17, we didn’t spend as much time on the other TSes as we did at a normal meeting, but we made progress on some of the TSes and will continue with all of them next time. In particular, the Reflection and 2D Graphics proposals received several hours of review each and are making great progress; at our next meeting we’ll continue with Ranges, Networking, Library Fundamentals 2, Parallelism 2, Modules, Coroutines, Contracts, and more.

What’s next

This summer, we’re going to send out the feature-complete C++17 out for its major international comment ballot. After that, we’ll address ballot comments at the November 2016 and February-March 2017 meetings and plan to send C++17 out for its final approval ballot then.

Once C++17 ships next year, I expect we’ll start looking at merging more of the TS “beta branches” into the C++ “trunk.” Here’s an updated snapshot of our status:

wg21-timeline

Thank you again to our host Symbio, to the over 100 experts at Oulu last week, and to the many more who participate in standardization through their national bodies, without whose efforts and willing collaborative spirit these results would not be achievable. The over four million C++ users worldwide benefit, and appreciate it very much too. Thank you, all, for your many contributions to Standard C++.