Feeds:
Posts
Comments

Archive for the ‘Uncategorized’ Category

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.

Read Full Post »

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.

 

Read Full Post »

[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.

Read Full Post »

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

Read Full Post »

[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.

Read Full Post »

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.

Read Full Post »

As CppCon begins, Stevens Capital Management is running an SCM Challenge quiz with questions provided by some CppCon speakers.(Creating a little login is required, in part so you can save progress, but they promise not to spam you.)

I’ve contributed a simple little question that’s directly related to my CppCon closing plenary session on Friday. By “simple little” I mean that my question itself is simple and can be illustrated well in a handful of short lines of code. Solving it with a valid answer is another matter, however. I wonder how many people will be able to give reasonable solutions[*] that pass the three short test cases…

Take a look, think about the question, and see if you can come up with a solution that works. Feel free to use the comments below to collaborate with others to solve the puzzle; if you’re at CppCon, use the great face time with other attendees to share possible solutions. If you succeed in writing a solution that prints “true” three times, they’ll email it to me and I’ll review it.

In my talk on Friday, I’ll present solutions to this and other lifetime problems. For those who aren’t here at CppCon in person, you’ll be able to catch the talk online on YouTube about a week later. (As always, all CppCon talks are being recorded and will be posted, but it will take a month or so to process and post all of the sessions — it takes a while to do professional-grade production for over 100 talks! Processing the plenary session videos is being expedited so that we can get those ones up quickly.)

I hope you enjoy the puzzle!

 

[*] No fair hardcoding a hack that artificially prints the right results for just these three cases. I know how to do that too, but that’s evading the problem, not solving it. :)

 

Read Full Post »

Older Posts »