The recent WG21 meeting in Oulu, Finland, was an especially busy one for the Library Working Group. Every day was spent working through the list of proposals intended for inclusion in C++17, and we also had three "evening" sessions that ran well past the evening (until nearly midnight, although the sun was still up to trick us into working late).

This post describes what I think are the most important library features that were reviewed and approved for inclusion in C++17. As usual, see Jason and Torvald's posts for news from the Core and Parallelism & Concurrency groups. As Jason explained, the main goal of the Oulu meeting was to finalize the content of the Committee Draft (CD) for C++17. The Library Working Group started the meeting with a huge number of papers intended for inclusion in the CD, and we managed to complete the review of almost all of them.

The biggest success is that we got std::variant, a type-safe union, into C++17. That has been working its way through the committee for some time and is finally in the working draft. P0088R3 is the final proposal, which was then modified by P0393R3 and P0032R3. That latter proposal changes the interfaces of std::variant, std::optional and std::any to be more consistent. Those three types are all different forms of "storage for a single object", but designed by different people at different times, and so they had unnecessary differences in API. For example, to test if a std::optional contained an object the original proposal required converting it to bool, whereas std::any has a .empty() member function. Now both have a .has_value() member function.

The C++ Standard Library has been rebased on the C11 Standard Library, rather than C99. This doesn't change much in practice, except for including (by reference) a few additional functions such as vfscanf() and aligned_alloc(). The optional parts of the C11 library such as <stdatomic.h> and <threads.h> are not included, because C++ already has its own atomic and thread facilities, and the Annex K "secure" extensions are also not included in C++. For full details see P0063R3. A related change was to explicitly declare all the functions that come from the C library in the synopses for the C++ headers. This changes nothing in practice, only the form of the specification in the C++ standard, but it makes the spec clearer as the signatures of all C functions are listed directly in the C++ standard.

C++17 adds the ability to extract an element from a map or set container, and then re-insert it into another container of similar type, without performing any memory allocations or constructor/destructor calls for the element. This works by simply "unhooking" the node from one container and updating the node's pointers to be part of another container. This feature has taken even longer to get ready than std::variant, but is there now. The accepted version of the proposal is P0083R3.

A small, but important, change was to rename the Uniform Random Number Generator concept that is modelled by various engines in the <random> header introduced in C++11. That name misleads people into thinking that those generators are general-purpose random number generators and that simply applying a modulus operation can produce a random value in the desired range. The problem with this is that it introduces a hard to detect bias, so the random numbers are not uniformly distributed. If g is a uniform random "number" generator that produces values in the range [0,99] inclusive, and you use (g() % 6) + 1 to simulate rolling a die then you will be simulating a loaded die. The values 1-4 each have a probability of 0.17 but the values 5 and 6 have a probability of 0.16.

The correct way to use g is with a random number distribution, like the ones defined in the <random> header, e.g. uniform_int_distribution, which produce correctly distributed values. To discourage people from using URNGs directly they have been renamed "uniform random bit generators". Time will tell if this makes any difference to the level of misuse. P0346R1 gives more rationale for the change.

A proposal was approved to add function to_chars() and from_chars(), for fast conversions of strings to/from numbers (both integers and floating point types). Those functions would not support localization or padding, or the other many features of printf(), so would be faster and simpler than using printf or iostreams for numeric conversions. Unfortunately due to some problems with the spec which were missed in the wording review, the changes couldn't be applied to the working draft, and so the functions are not in the CD going out for the National Body ballot. P0067R3 is the proposal; it's possible it will be rescued and still make it into C++17, but for now it's not in.

We also resolved 44 of the issues that had been reported against the standard library, far more than would usually be moved at a single meeting. The usual process is to resolve only issues that have been "Ready" since the previous meeting, and then move other issue to "Ready" where they can sit until the next meeting, giving people time to object to the change (maybe based on implementation experience). We wanted to get as many fixes into the CD as possible and they're more likely to get a thorough review in the CD than by sitting in the issues lists for another few months. Of those 44 issues nearly half were problems noticed in the Filesystem library (which graduated from a TS to the C++17 at the last meeting). A number of those problems were present in GCC's implementation of the Filesystem TS, and are either fixed already or will be soon.

Last updated: March 16, 2023