Feeds:
Posts
Comments

The ISO C++ committee had its winter meeting in Kona, HI, USA from February 27 to March 4, hosted by Plum Hall and the Standard C++ Foundation. Over 100 people attended, officially representing 9 countries.

C++17 is done!

The big news is that we completed C++17, which dominated the work of the meeting: C++17 is now technically finished and being sent out for its final ISO balloting. All that remains for C++17 now is some ISO red tape and minor touch-up to get it officially published, which is expected to be just mechanical.

There’s not much exciting to report from a “new features added at this meeting” point of view, because the main work was to finish resolving national body review comments on C++17 and ship the product. Perhaps the most exciting thing was that we decided to add the std::byte type; the rest of the work was final pre-release bug fixes before casting C++17 in stone, the important-but-unsung work of getting a product to ship quality.

Thank you very much to everyone who contributed in person or through papers, email, telecons and otherwise to creating and shipping C++17 — as well as several TSes that we also worked on concurrently and will soon be considering to add early in the C++20 cycle! Your hard work is much appreciated by everyone. I especially want to call out the Library working group (LWG) members, who had the heaviest C++17 workload in Kona and worked around the clock every day to finish responding to the comments in their areas. Thanks again, everyone. Here’s a group photo we took just outside our main meeting room (directly behind us) right after approving C++17:

Kona2017 full committee - crop

Next, we’re already shifting gears to begin work on C++20 at our next meeting this July in Toronto.

Other progress

We also approved shipping the Coroutines TS out for its (expected-to-be-only) international comment ballot, aka PDTS (Proposed Draft Technical Specification).

We came oh-so-close to approve shipping the Modules TS out for PDTS as well. The Evolution working group (EWG) weighed in on whether a couple of final cases should be included before sending it out for comments, and we hope to finalize that feature set and send it out in July in Toronto.

We also did work on the Parallelism 2 TS, and on a number of pre-TS proposals including 2D Graphics. On a personal note, my comparisons proposal was positively reviewed by both EWG and the Library Evolution working group (LEWG) (only the core proposal was encouraged, none of the parts marked ‘optional’) and wouldn’t have got that far without standing on the shoulders of giants — the previous comparisons proposals listed in the paper, notably Bjarne Stroustrup’s efforts and again Jens Maurer’s writing the standardese wording for Bjarne and now for me — and the detailed comments of over two dozen reviewers many of whom did detailed reviews of multiple drafts (it was a busy winter) — thank you again to everyone who helped me with that, it is at least 2x better as a result. If people are interested, I might give a short talk about it at CppCon this fall.

The Reflection proposal has now progressed out of the incubator Study Group, and was presented to the main Evolution and Library Evolution subgroups for the first time. To handle related proposals, the Reflection Study Group’s charter is now being expanded to also include proposals toward a general first-class compile-time programming model. For anyone who loves the glorious compile-time magic that C++ template metaprogramming (TMP) is able to do, but wish it could both do much more and also not be template metaprogramming with angle brackets and inscrutable code and diagnostics, then you’ll love the work in this direction; think “constexpr on steroids.” I’m looking forward to seeing how this evolves.

Both the Networking TS and the Ranges TS successfully completed their only (PDTS) ballots before Kona. The only work that remains before finalizing those is to address their PDTS ballot comments, which will largely be done in LWG. LWG was fully booked all week long with C++17 CD comments, but on Saturday started processing the PDTS comments as well. We plan to finish resolving Networking and Ranges comments and finalize those TSes at our next meeting in July.

In EWG, we looked at some feedback on the Concepts TS with an eye toward hopefully merging the Concepts TS into the C++20 working paper early in the C++20 cycle — possibly as soon as this year. There was one design tweak that EWG approved, and a couple more that will likely be discussed again in July in Toronto.

Here is an updated snapshot of our status, also available on the status page:

wg21-timeline-2017-03.png

Thank you again to the over 100 experts in Kona, and the many more who participate in standardization through their national bodies! Have a good spring… next stop: Toronto, to start C++20 this July.
Correction, 3/25: The original text did not reflect that LWG additionally spent a lot of time on Saturday processing Ranges PDTS issues. LWG did (thanks!), so we actually have a head start on those. As originally stated, we expect to complete the Ranges TS and Networking TS in July, and the Kona head start on PDTS comment resolution makes doing so that much easier.

This discussion today on the Core Guidelines repo issues is probably of broad interest. It’s regarding why we chose to annotate not_null<T*> rather than the reverse in the Guidelines and the Guideline Support Library (GSL).

Pasting here:


I would take this interface reduction one step further and make an un-annotated T* implicitly “not null”.

I understand, and we considered that.

We decided against that for several reasons:

  • T*, smart_ptr<T>, span<T>, container<T>::iterator, range<T>, etc. are all non-owning indirections and should be consistent with each other — it would be strange for some to be nullable but not others. Iterators can be “null”, for example a default-constructed iterator is not referring to anything.
  • More generally, all of those can be default-constructed, and the only reasonable semantics for that are “doesn’t point to anything.” (This can be a springboard for a broader discussion about the situations where default-constructible types are important, Regular types, etc.)
  • A large fraction of existing of T* are deliberately intended to be null, because people by convention use references for not-null parameters in particular and so in modern C++ code the presence of a T*parameter often (not always) implies nullability by that convention. So trying to annotate the “nullable” case is a huge code churn, and not only unadoptable but actually against the intent of much existing code.
  • Even if we ignored that and changed the default for T*, then we’d need to invent yet another annotation wrapper such as nullable<T>, and have to teach and explain both not_null<T> and nullable<T> (inconsistently).

For these and other reasons, we think that pointers should be nullable by default unless annotated otherwise.

valid concerns that are being dismissed because of a failure to distinguish between best practices for new code, and pragmatic recommendations for updating old code

I hope that helps reassure you that the concerns were considered deeply and aren’t being dismissed, and apply both to new code and old code. Defaults are important, and should reflect the common case especially for new code, but also for old code much of which is “correct” but just expressed without enough information about the intent because the programmer didn’t have the option or tool to express the intent.

The key issue is to distinguish maybe-null and never-null in the type system, and both of our approaches agree on doing that. Tony Hoare called null pointers his “billion-dollar mistake,” but in my opinion, and I think yours, the mistake was not maybe-null pointers (which are necessary, unavoidable, and pervasively present in every language with pointer/reference indirections, including Java, C#, C, C++, etc.), but rather in not distinguishing maybe-null and never-null pointers in the type system. You and we are both trying to do that, and so in the above I think we’re largely agreeing and our discussion is narrowly just about which one should be the default.

 

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.

[ETA: Mentioning specific TSes expected to be merged soon post-C++17.]

On Saturday, the ISO C++ committee completed its fall meeting in Issaquah, WA, USA, hosted by Microsoft and the Standard C++ Foundation. We had over 110 people at the meeting, representing 10 national bodies. We also had more than usual local visitors – note that ISO C++ meetings are open and we always welcome people who are curious to see what goes on. As usual, we met for six days Monday through Saturday, including several evenings. Fun historical note: This meeting was held in the same hotel as the meeting that completed and shipped C++14.

The following are some highlights of what we achieved last 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.”

C++17 completed its comment ballot, first of two (expected) meetings to address comments

Draft C++17 hit its major feature-freeze at our previous meeting, and over the summer we conducted its major ISO comment ballot. So the primary focus at this meeting was addressing the review comments. Think of it as the “shakedown” stage of fixing bugs before release.

We expected to take two meetings to resolve all the comments, and we are on track. So at our next meeting we hope to finish addressing the ballot comments and any other fixes we can resolve and hopefully set C++17 in stone as we send it out for its possibly-final formal approval ballot. (ISO administrative detail: I say “possibly-final” because as long as that ballot comes back with zero No votes, we can skip the actual final extra ballot, as we did with C++14. If for some reason it doesn’t, we’d run one more ballot over the summer. Either way, we’ll be done in 2017.)

We made some minor adjustments. For example, the std::variant type was tweaked to make it clear that Ts cannot be empty or contain void or T& reference types.

Although we didn’t add any new features, we did agree to finally remove one: Old-style dynamic exception specifications were already deprecated, and have now been officially removed from the standard. They are superseded by noexcept.

Other progress

Besides resolving C++17 ballot comments, we also worked on the TSes: We completed one, sent two out for their main ballots, and have two more expected to go out for their main ballots at the next meeting.

Here is a summary of progress, in rough order of expected delivery dates, starting with what we actually finished at this meeting:

The Library Fundamentals 2 TS is now done. This is another round of “beta” standard library extensions, and at this meeting we completed resolving its comment ballot results and approved sending the final text for publication.

The Networking TS and Ranges TS both reached feature-freeze and were sent out for their comment ballots. Both are expected to be completed and published in 2017.

The Modules TS and Coroutines TS are both “almost” ready to go out for their comment ballots. Both very nearly made it this time, but they need some final review and we expect both to go out for their comment ballots at our next meeting this winter. Depending on timing, they too might be done and published in 2017.

The Parallelism 2 TS is in progress and should reach its comment ballot in a small number of meetings. The big news here is that it seems the concurrency subgroup has finally agreed on a unified executors proposal, which is important to be able to say “where” a piece of concurrent or parallel work executes. This is an important milestone and the result of copious amounts of effort across several meetings.

We also continued incubating other work. In particular, the Reflection study group reviewed the latest merged static reflection proposal and found it ready to enter the main Evolution groups at our next meeting to start considering the unified static reflection proposal for a TS or for the next standard.

What’s next

A lot of our C++ standardization work is reaching “ship stage” at about the same time, which is pretty exciting to see, so we’re in the middle of a busy handful of meetings. At our next March 2017 meeting, we hope to finish addressing the ballot comments and plan to send C++17 out for its final approval ballot. We also expect to send out a few more TS “beta” branches out for review as mentioned above.

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,” including the published TSes that didn’t make the C++17 merge (notably Concepts and Concurrency). Here’s an updated snapshot of our status:

wg21-timeline

Thank you again to the over 110 experts at Issaquah last week, and the many more who participate in standardization through their national bodies! Have a good winter.

You can find it on YouTube here. [ETA: Slides are here.] Here’s an embed, below:

[edited to add notes and apply Howard Hinnant’s de-escalation to static_cast]

After my talk on Friday, a couple of people asked me how I was storing destructors in my gcpp library. Since several people are interested, I thought I’d write a note.

The short answer is to store two raw pointers: one to the object, and one to a type-erased destructor function that’s handy to write using a lambda.

In deferred_heap.h, you’ll see that the library stores a deferred destructor as:

struct destructor {
    const void* p;
    void(*destroy)(const void*);
};

So we store two raw pointers, a raw pointer to the object to be destroyed and a raw function pointer to the destructor. Then later we can just invoke d.destroy(d.p).

The most common question is: “But how can you get a raw function pointer to the destructor?” I use a lambda:

// Called indirectly from deferred_heap::make<T>.
// Here, t is a T&.
dtors.push_back({
    std::addressof(t), // address of object
    [](const void* x) { static_cast<const T*>(x)->~T(); }
});                    // dtor to invoke

A non-capturing lambda has no state so it can be used as a plain function, and because we know T here we just write a lambda that performs the correct cast back to invoke the correct T destructor. So for each distinct type T that this is instantiated with, we generate one T-specific lambda function (on demand at compile time, globally unique) and we store that function’s address.

Notes:

  • The lambda gives a handy way to do type erasure in this case. One line removes the type, and the other line adds it back.
  • Yes, it’s legal to call the destructor on a const object. It has to be; we have to be able to destroy const objects. Const never applies to a constructor or destructor, it applies to all the other member functions.
  • Some have asked what the body of the wrapper lambda generates. I looked at the code gen in Clang a couple of weeks ago, and depending on the optimization level, the lambda is generated as either a one-instruction function (just a single jmp to the actual destructor) or as a copy of the destructor if it’s inlined (no run-time overhead at all, just another inline copy of the destructor in the binary if it’s generally being inlined anyway).
  • Because we are storing the destructor at the same time as we are constructing the T object, we know the complete object’s type is T and therefore can easily store the correct destructor for the complete object. Later, regardless of whether the list deferred_ptr keeping it alive is a deferred_ptr<T> or something else, such as a deferred_ptr<const T> or deferred_ptr<BaseClass> or deferred_ptr<TDataMember>, the correct T destructor will be called to clean up the complete object.

I’ve now added a version of this to the gcpp readme FAQ section.

Thanks to everyone who responded to the little puzzle for CppCon that I posted on the weekend. I’ll show a couple of answers in my talk tomorrow at the conference, which will be recorded and should be available on YouTube in a week or so.

My talk will focus primarily on how to use the great std:: facilities we already have in today’s C++, especially scoped lifetime, unique_ptr, and shared_ptr. Those are what you should prefer to use, in that order, to express object lifetimes in C++. In many basic situations, those tools let you express lifetime by construction with complete automation, good performance, and no extra coding work — the bee’s knees!

However, in some advanced situations, using today’s tools does still involve writing some manual code. In my talk I’ll cover how to do that by hand today.

Then at the end of the talk if time allows, I’ll offer some “very experimental” thoughts exploring whether some of that remaining manual code might be automatable, just as we automated single-owner-new/delete with unique_ptr, and automated multi-owner-new/delete-plus-reference-counting with shared_ptr and weak_ptr. To try the ideas out, I wrote a little demo library I call gcpp [GitHub]. You can read about it at that link (but please also read the disclaimers!) and I’ll present parts of it at the end of my talk tomorrow if there’s time. Like any experiment, in the worst case it won’t work out and the ideas will be abandoned; in the best case, my hope is that it may contribute some interesting ideas to develop further.