Botond Ballo: Trip Report: C++ Standards Meeting in Cologne, July 2019 |
Project | What’s in it? | Status |
C++20 | See below | On track |
Library Fundamentals TS v3 | See below | Under development |
Concepts | Constrained templates | In C++20 |
Parallelism TS v2 | Task blocks, library vector types and algorithms, and more | Published! |
Executors | Abstraction for where/how code runs in a concurrent context | Targeting C++23 |
Concurrency TS v2 | See below | Under active development |
Networking TS | Sockets library based on Boost.ASIO | Published! Not in C++20. |
Ranges | Range-based algorithms and views | In C++20 |
Coroutines | Resumable functions (generators, tasks, etc.) | In C++20 |
Modules | A component system to supersede the textual header file inclusion model | In C++20 |
Numerics TS | Various numerical facilities | Under active development |
C++ Ecosystem TR | Guidance for build systems and other tools for dealing with Modules | Under active development |
Contracts | Preconditions, postconditions, and assertions | Pulled from C++20, now targeting C++23 |
Pattern matching | A match -like facility for C++ |
Under active development, targeting C++23 |
Reflection TS | Static code reflection mechanisms | Publication imminent |
Reflection v2 | A value-based constexpr formulation of the Reflection TS facilities |
Under active development, targeting C++23 |
Metaclasses | Next-generation reflection facilities | Early development |
A few links in this blog post may not resolve until the committee’s post-meeting mailing is published (expected within a few days of August 5, 2019). If you encounter such a link, please check back in a few days.
Last week I attended a meeting of the ISO C++ Standards Committee (also known as WG21) in Cologne, Germany. This was the second committee meeting in 2019; you can find my reports on preceding meetings here (February 2019, Kona) and here (November 2018, San Diego), and previous ones linked from those. These reports, particularly the Kona one, provide useful context for this post.
This week the committee reached a very important milestone in the C++20 publication schedule: we approved the C++20 Committee Draft (CD), a feature-complete draft of the C++20 standard which includes wording for all of the new features we plan to ship in C++20.
The next step procedurally is to send out the C++20 CD to national standards bodies for a formal ISO ballot, where they have the opportunity to comment on it. The ballot period is a few months, and the results will be in by the next meeting, which will be in November in Belfast, Northern Ireland. We will then spend that meeting and the next one addressing the comments, and then publishing a revised draft standard. Importantly, as this is a feature-complete draft, new features cannot be added in response to comments; only bugfixes to existing features can be made, and in rare cases where a serious problem is discovered, a feature can be removed.
Attendance at this meeting once again broke previous records, with over 200 people present for the first time ever. It was observed that one of the likely reasons for the continued upward trend in attendance is the proliferation of domain-specific study groups such as SG 14 (Games and Low-Latency Programming) and SG 19 (Machine Learning) which is attracting new experts from those fields.
Note that the committe now tracks its proposals in GitHub. If you’re interested in the status of a proposal, you can find its issue on GitHub by searching for its title or paper number, and see its status — such as which subgroups it has been reviewed by and what the outcome of the reviews were — there.
Here are the new changes voted into C++20 Working Draft at this meeting. For a list of changes voted in at previous meetings, see my Kona report. (As a quick refresher, major features voted in at previous meetings include modules, coroutines, default comparisons (<=>
), concepts, and ranges.)
constexpr
improvements:
constexpr
containers. This is the language change that allows the library changes mentioned below to make std::vector
and std::string
constexpr
.constinit
keywordconstexpr
contextsconstexpr
intrinsics by permitting unevaluated inline assembly in constexpr
functions<=>
):
using enum
. This allows introducing the enumerators of a scoped enumeration into a local scope, and thereby avoiding the repetition of the enumeration name in that scope.[[nodiscard("should have a reason")]]
[[nodiscard]]
for constructors. This is also a Defect Report against C++17.matrix[row, col]
) in a future standard.volatile
(only the core language portions; the library portions are still under review)memory_order_consume
with release sequencesatomic_ref
, and add wait/notify to atomic
std::vector
constexpr
std::string
constexpr
source_location
for C++20. This provides a modern replacement for macros like __FILE__
and __LINE__
.PascalCase
to snake_case
, for consistency with other standard library names, and tweaks the names further in cases where the mechanical rename results in a conflict or other issue.<=>
to standard libary types)to_array
from LFTS with updatesbasic_stringbuf
‘s bufferconstexpr
INVOKEbasic_istream_view::iterator
should not be copyablechrono
char8_t
backward compatibility remediationbind_front
should not unwrap reference_wrapper
ContiguousIterator
ceil2
constexpr
feature macro concernsIn addition to the C++ International Standard (IS), the committee publishes Technical Specifications (TS) which can be thought of experimental “feature branches”, where provisional specifications for new language or library features are published and the C++ community is invited to try them out and provide feedback before final standardization.
At this meeting, the focus was on the C++20 CD, and not so much on TSes. In particular, there was no discussion of merging TSes into the C++ IS, because the deadline for doing so for C++20 was the last meeting (where Modules and Coroutines were merged, joining the ranks of Concepts which was merged a few meetings prior), and it’s too early to be discussing mergers into C++23.
Nonetheless, the committee does have a few TSes in progress, and I’ll mention their status:
The Reflection TS was approved for publication at the last meeting. The publication process for this TS is a little more involved than usual: due to the dependency on the Concepts TS, the Reflection TS needs to be rebased on top of C++14 (the Concepts TS’ base document) for publication. As a result, the official publication has not happened yet, but it’s imminent.
As mentioned before, the facilities in the Reflection TS are not planned to be merged into the IS in their current form. Rather, a formulation based on constexpr
values (rather than types) is being worked on. This is a work in progress, but recent developments have been encouraging (see the SG7 (Reflection) section) and I’m hopeful about them making C++23.
This third iteration (v3) of the Library Fundamentals TS continues to be open for new features. It hasn’t received much attention in recent meetings, as the focus has been on libraries targeted at C++20, but I expect it will continue to pick up material in the coming meetings.
A concrete plan for Concurrency TS v2 is starting to take shape.
The following features are planned to definitely be included:
fiber_context
. This is the latest formulation of stackful coroutines (fibers). It’s a very long time in the making, and has been bounced around various strudy groups for years; I’m glad to see it finally have a concrete ship vehicle!The following additional features might tag along if they’re ready in time:
I don’t think there’s a timeline for publication yet; it’s more “when the features in the first list are ready”.
As mentioned before, the Networking TS did not make C++20. As it’s now targeting C++23, we’ll likely see some proposal for design changes between now and its merger into C++23.
One such potential proposal is one that would see the Networking TS support TLS out of the box. JF Bastien from Apple has been trying to get browser implementers on board with such a proposal, which might materialize for the upcoming Belfast meeting.
As usual, I spent most of the week in EWG. Here I will list the papers that EWG reviewed, categorized by topic, and also indicate whether each proposal was approved, had further work on it encouraged, or rejected. Approved proposals are targeting C++20 unless otherwise mentioned; “further work” proposals are not.
standard_case
for C++20, while we still can. Concepts have been part of the C++ literature long before the C++20 language feature that allows them to be expressed in code; for example, they are discussed in Stepanov’s Elements of Programming, and existing versions of the IS document describe the notional concepts that form the requirements for various algorithms. In this literature, concepts are conventionally named in PascalCase
. As a result, the actual language-feature concepts added to the standard library in C++20 were named in PascalCase
as well. However, it was observed that essentially every other name in the standard library uses snake_case
, and remaining consistent with that might be more important than respecting naming conventions from non-code literature. This was contentious, for various reasons: (1) it was late in the cycle to make this change; (2) a pure mechanical rename resulted in some conflicts with existing names, necessitating additional changes that went beyond case; and (3) some people liked the visual distinction that PascalCase
conferred onto concept names. Nonetheless, EWG approved the change.expression -> Type
, because their semantics are not consistent with trailing return types which share the same syntax.Contracts were easily the most contentious and most heavily discussed topic of the week. In the weeks leading up the meeting, there were probably 500+ emails on the committee mailing lists about them.
The crux of the problem is that contracts can have a range of associated behaviours / semantics: whether they are checked, what happens if they are checked and fail, whether the compiler can assume them to be true in various scenarios, etc. The different behaviours lend themselves to different use cases, different programming models, different domains, and different stages of the software lifecycle. Given the diversity of all of the above represented at the committee, people are having a really hard time agreeing on what set of possible behaviours the standard should allow for, what the defaults should be, and what mechanisms should be available to control the behaviour in case you want something other than the defaults.
A prominent source of disagreement is around the possibility for contracts to introduce undefined behaviour (UB) if we allow compilers to assume their truth, particularly in cases where they are not checked, or where control flow is allowed to continue past a contract failure.
Contracts were voted into the C++20 working draft in June 2018; the design that was voted in was referred to as the “staus quo design” during this week’s discussions (since being in the working draft made it the status quo). In a nutshell, in the status quo design, the programmer could annotate contracts as having one of three levels — default
, audit
, or axiom
— and the contract levels were mapped to behaviours using two global switches (controlled via an implementation-defined mechanism, such as a compiler flag): a “build level” and a “continuation mode”.
The status quo design clearly had consensus at the time it was voted in, but since then that consensus had begun to increasingly break down, leading to a slew of Contracts-related proposals submitted for the previous meeting and this one.
I’ll summarize the discussions that took place this week, but as mentioned above, the final outcome was that Contracts was removed from C++20 and is now targeting C++23.
EWG discussed Contracts on two occasions during the week, Monday and Wednesday. On Monday, we started with a scoping discussion, where we went through the list of proposals, and decided which of them we were even willing to discuss. Note that, as per the committee’s schedule for C++20, the deadline for making design changes to a C++20 feature had passed, and EWG was only supposed to consider bugfixes to the existing design, though as always that’s a blurry line.
Anyways, the following proposals were rejected with minimal discussion on the basis of being a design change:
That left the following proposals to be considered. I list them here in the order of discussion. Please note that the “approvals” from this discussion were effectively overturned by the subsequent removal of Contracts from C++20.
default
, audit
, and axiom
), as well as the build level and continuation mode, and made the way the behaviour of a contract checking statement is determined completely implementation-defined. The second part essentially layered on top the “Contracts that work” proposal, which introduces literal semantics: rather than annotating contracts with “levels” which are somehow mapped onto behaviours, contracts are annotated with their desired behaviour directly; if the programmer wants different behaviours in different build modes, they can arrange for that themselves, using e.g. macros that expand to different semantics in different build modes. EWG approved both parts, which was somewhat surprising because “Contracts that work” was previously voted as not even being in scope for discussion. I think the sentiment was that, while this is a design change, it has more consensus than the status quo, and so it’s worth trying to sneak it in even though we’re past the design change deadline. Notably, while this proposal did pass, it was far from unanimous, and the dissenting minority was very vocal about their opposition, which ultimately led to the topic being revisited and Contracts being axed from C++20 on Wednesday.To sum up what happened on Monday: EWG made a design change to Contracts, and that design change had consensus among the people in the room at the time. Unfortunately, subsequent discussions with people not in the room, including heads of delegations from national standards bodies, made it clear that the design change was very unlikely to have the consensus of the committee at large in plenary session, largely for timing reasons (i.e. it being too late in the schedule to make such a nontrivial design change).
As people were unhappy with the status quo, but there wasn’t consensus for a design change either, that left removing contracts from C++20 and continuing to work on it in the C++23 cycle. A proposal to do so was drafted and discussed in EWG on Wednesday, with a larger group of people in attendance this time, and ultimately garnered consensus.
To help organize further work on Contracts in the C++23 timeframe, a new Study Group, SG 21 (Contracts) was formed, which would incubate and refine an updated proposal before it comes back to EWG. It’s too early to say what the shape of that proposal might be.
I personally like literal semantics, though I agree it probably wouldn’t have been prudent to make a significant change like that for C++20. I would welcome a future proposal from SG 21 that includes literal semantics.
A notable procedural development in the area of Modules, is that the Modules Study Group (SG 2) was resurrected at the last meeting, and met during this meeting to look at all Modules-related proposals and make recommendations about them. EWG then looked at the ones SG 2 recommended for approval for C++20:
#include
directives into module imports) optional, because it is problematic for some use cases, and solves the problems that motivated mandatory include translation in another way. (Aside: Richard Smith, the esteemed author of this paper and the previous one, clearly has too much time on his hands if he can come up with alliterations like this for paper titles. We should give him some more work to do. Perhaps we could ask him to be the editor of the C++ IS document? Oh, we already did that… Something else then. Finish implementing Concepts in clang perhaps?
) using import
rather than #include
(without imposing any requirements (yet) that their contents actually be modularized). It also reserves module names whose first component is std
, or std
followed by a number, for use by the standard library.import
keyword in such a way that tools can quickly scan source files and gather their module dependencies without having to do too much processing (and in particular without having to do a full run of the preprocessor).There were also some Modules-related proposals that SG2 looked at and decided not to advance for C++20, but instead continue iterating for C++23:
inline
keyword is not in line with the design of modules. This proposal will be revised before EWG looks at it.inline
keyword explicitly). Reactions were somewhat mixed, with some concerns about impacts on compile-time and runtime performance. Some felt that if we do this at all, we should do it in C++20, so our guidance to authors of modular code can be consistent from the get-go; while it seems to be too late to make this change in C++20 itself, the idea of a possible future C++20 Defect Report was raised.Finally, EWG favourably reviewed at the Tooling Study Group’s plans for a C++ Ecosystem Technical Report. One suggestion made was to give the TR a more narrowly scoped name to reflect its focus on Modules-related tooling (lest people are misled into expecting that it addresses every “C++ Ecosystem” concern).
EWG considered several proposed improvements to coroutines. All of them were rejected for C++20 due to being too big of a change at this late stage.
co_return;
and co_return value;
in the same coroutineco_await
/co_yield
/co_return
ugliness by making yield
etc. context-sensitive keywords.Coroutines will undoubtedly see improvements in the C++23 timeframe, including possibly having some of the above topics revisited, but of course we’ll now be limited to making changes that are backwards-compatible with the current design.
constexpr
constexpr
intrinsics by permitting unevaluated inline assembly in constexpr
functions. With std::is_constant_evaluated()
, you can already give an operation different implementations for runtime and compile-time evaluation. This proposal just allows the runtime implementations of such functions to use inline assembly.constinit
: EWG was asked to clarify the intended rules for non-initializing declarations. The Core Working Group’s recommendation — that a non-initializing declaration of a variable be permitted to contain constinit
, and if it does, the initializing declaration must be constinit
as well — was accepted.In one of the meeting’s more exciting developments, Herb Sutter’s lightweight exceptions proposal (affectionately dubbed “Herbceptions” in casual conversation) was finally discussed in EWG. I view this proposal as being particularly important, because it aims to heal the current fracture of the C++ user community into those who use exceptions and those who do not.
The proposal has four largely independent parts:
std::logic_error
, but rather via a contract violation.noexcept
. However, that’s unlikely to fly, as there are good use cases for recovering from allocation failure, so more recent versions leave the choice of behaviour up to the allocator, and aim to make such functions conditionally noexcept
.try
keyword, not unlike Rust’s try!
macro. Of course, unlike Rust, use of the annotation would have to be optional for backwards compatibility, though one can envision enforcing its use locally in a codebase (or part of a codebase) via static analysis.As can be expected from such an ambitious proposal, this prompted a lot of discussion in EWG. A brief summary of the outcome for each part:
noexcept
, there was no consensus to move in the direction of making the default allocator non-throwing.I expect the proposal will return in revised form (and this will likely repeat for several iterations). The road towards achieving consensus on a significant change like this is a long one!
I’ll mention one interesting comment that was made during the proposal’s presentation: it was observed that since we need to revise the calling convention as part of this proposal anyways, perhaps we could take the opportunity to make other improvements to it as well, such as allowing small objects to be passed in registers, the lack of which is a pretty unfortunate performance problem today (certainly one we’ve run into at Mozilla multiple times). That seems intriguing.
for ...
” construct which could be used to iterate at compile time over tuple-like objects and parameter packs. Prior to this meeting, it was discovered that the parameter pack formulation has an ambiguity problem. We couldn’t find a fix in time, so the support for parameter packs was dropped, leaving only tuple-like objects. However, “for ...
” no longer seemed like an appropriate syntax if parameter packs are not supported, so the syntax was changed to “template for
“. Unfortunately, while EWG approved “template for
“, the Core Working Group ran out of time to review its wording, so (*) the feature didn’t make C++20. It will likely be revisited for C++23, possibly including ways to resolve the parameter pack issue.(Disclaimer: don’t read too much into the categorization here. One person’s bug fix is another’s feature.)
For C++20:
rethrow_exception
must be allowed to copy. This is a small bugfix to an exception handling support utility.[[nodiscard]]
for constructors. This fixes what was largely a wording oversight.For C++23:
operator new
. This allows operator new
to communicate to its caller how many bytes it actually allocated, which can sometimes be larger than the requested amount.enum class
es from plan enum
s, which is not necessarily possible to do in pure library code.size_t
and ptrdiff_t
. The suffixes uz
for size_t
and z
for ssize_t
were approved. The suffixes t
for ptrdiff_t
and ut
for a corresponding unsigned type had no consensus.[[always_inline]]
and [[never_inline]]
. EWG was generally supportive, but requested the author provide additional motivation, and also clarify if they are orders to the compiler (usable in cases where inlining or not actually has a semantic effect), or just strong optimization hints.As usual, there were papers EWG did not get to discussing at this meeting; see the committee website for a complete list. At the next meeting, after addressing any national body comments on the C++20 CD which are Evolutionary in nature, EWG expects to spend the majority of the meeting reviewing C++23-track proposals.
Evolution Incubator, which acts as a filter for new proposals incoming to EWG, met for two days, and reviewed numerous proposals, approving the following ones to advance to EWG at the next meeting:
auto(x)
: decay-copy in the language. This is a construct for performing explicitly the “decay” that values undergo implicitly today when being passed as a function argument by value.int...
(more generally, A...
where A
is not a template parameter), where all elements of the pack have the same type.short float
proposal. They will be seen by Library Evolution as well.Having sat in the Evolution group, I haven’t been able to follow the Library groups in any amount of detail, but I’ll call out some of the library proposals that have gained design approval at this meeting:
std::to_underlying()
std::apply()
constexpr
bitsetbasic_string::resize_default_init
starts_with()
and ends_with()
volatile
pointerssnapshot_source()
contains()
for string
Note that the above is all C++23 material; I listed library proposals which made C++20 at this meeting above.
There are also efforts in place to consolidate general design guidance that the Library Evolution group would like to apply to all proposals into a policy paper.
While still at the Incubator stage, I’d like to call attention to web_view
, a proposal for embedding a view powered by a web browser engine into a C++ application, for the purpose of allowing C++ applications to leverage the wealth of web technologies for purposes such as graphical output, interaction, and so on. As mentioned in previous reports, I gathered feedback about this proposal from Mozilla engineers, and conveyed this feedback (which was a general discouragement for adding this type of facility to C++) both at previous meetings and this one. However, this was very much a minority view, and as a whole the groups which looked at this proposal (which included SG13 (I/O) and Library Evolution Incubator) largely viewed it favourably, as a promising way of allow C++ applications to do things like graphical output without having to standardize a graphics API ourselves, as previously attempted.
SG 1 has a busy week, approving numerous proposals that made it into C++20 (listed above), as well as reviewing material targeted for the Concurrency TS v2 (whose outline I gave above).
Another notable topic for SG 1 was Executors, where a consensus design was reviewed and approved. Error handling remains a contentious issue; out of two different proposed mechanics, the first one seems to have the greater consensus.
Progress was also made on memory model issues, aided by the presence of several memory model experts who are not regular attendees. It seems the group may have an approach for resolving the “out of thin air” (OOTA) problem (see relevant papers); according to SG 1 chair Olivier Giroux, this is the most optimistic the group has been about the OOTA problem in ~20 years!
The Compile-Time Programming Study Group (SG 7) met for half a day to discuss two main topics.
First on the agenda was introspection. As mentioned in previous reports, the committee put out a Reflection TS containing compile-time introspection facilities, but has since agreed that in the C++ IS, we’d like facilities with comparable expressive power but a different formulation (constexpr
value-based metaprogramming rather than template metaprogramming). Up until recently, the nature of the new formulation was in dispute, with some favouring a monotype approach and others a richer type hierarchy. I’m pleased to report that at this meeting, a compromise approach was presented and favourably reviewed. With this newfound consensus, SG 7 is optimistic about being able to get these facilities into C++23. The compromise proposal does require a new language feature, parameter constraints, which will be presented to EWG at the next meeting.
(SG 7 also looked at a paper asking to revisit some of the previous design choices made regarding parameter names and access control in reflection. The group reaffirmed its previous decisions in these areas.)
The second main topic was reification, which can be thought of as the “next generation” of compile-time programming facilities, where you can not only introspect code at compile time, but perform processing on its representation and generate (“reify”) new code. A popular proposal in this area is Herb Sutter’s metaclasses, which allow you to “decorate” classes with metaprograms that transform the class definition in interesting ways. Metaclasses is intended to be built on a suite of underlying facilties such as code injection; there is now a concrete proposal for what those facilities could look like, and how metaclasses could be built on top of them. SG 7 looked at an overview of this proposal, although there wasn’t time for an in-depth design review at this stage.
The Tooling Study Group (SG 15) met for a full day, focusing on issues related to tooling around modules, and in particular proposals targeting the C++ Modules Ecosystem Technical Report mentioned above.
I couldn’t be in the room for this session as it ran concurrently with Reflection and then Herbceptions in EWG, but my understanding is that the main outcomes were:
clang-scan-deps
), and the committee has made efforts to make them tractable (see e.g. the tweak to the context-sensitivity rules for import
which EWG approved this week).A proposal for a file format for describing dependencies of source files was also reviewed, and will continue to be iterated on.
One observation that was made during informal discussion was that SG 15’s recent focus on modules-related tooling has meant less time available for other topics such as package management. It remains to be seen if this is a temporary state of affairs, or if we could use two different study groups working in parallel.
Other Study Groups that met at this meeting include:
web_view
, 2D graphics (which continues to be iterated on in the hopes of a revised version gaining consensus), as well as few proposals related to callbacks which are relevant to the design of I/O facilities.In addition, as mentioned, a new Contracts Study Group (SG 21) was formed at this meeting; I expect it will have its inaugural meeting in Belfast.
Most Study Groups hold regular teleconferences in between meetings, which is a great low-barrier-to-entry way to get involved. Check out their mailing lists here or here for telecon scheduling information.
The next meeting of the Committee will be in Belfast, Northern Ireland, the week of November 4th, 2019.
My highlights for this meeting included:
constexpr
dynamic allocation, including constexpr vector
and string
for C++20-fno-exceptions
segment of C++ users back into the foldDue to the sheer number of proposals, there is a lot I didn’t cover in this post; if you’re curious about a specific proposal that I didn’t mention, please feel free to ask about it in the comments.
Other trip reports about this meeting include Herb Sutter’s and the collaborative Reddit trip report — I encourage you to check them out as well!
https://botondballo.wordpress.com/2019/07/26/trip-report-c-standards-meeting-in-cologne-july-2019/
Комментировать | « Пред. запись — К дневнику — След. запись » | Страницы: [1] [Новые] |