Summary / TL;DR
<!–
–>
Project | What’s in it? | Status |
C++17 | See list | Published! |
C++20 | See below | On track |
Library Fundamentals TS v3 | See below | Under active development |
Concepts TS | Constrained templates | Merged into C++20, including (now) abbreviated function templates! |
Parallelism TS v2 | Task blocks, library vector types and algorithms, and more | Published! |
Executors | Abstraction for where/how code runs in a concurrent context | Subset headed for C++20, rest in C++23 |
Concurrency TS v2 | See below | Under development. Depends on Executors. |
Networking TS | Sockets library based on Boost.ASIO | Published! Not headed for C++20. |
Ranges TS | Range-based algorithms and views | Merged into C++20! |
Coroutines TS | Resumable functions, based on Microsoft’s await design |
Published! C++20 merge uncertain |
Modules v1 | A component system to supersede the textual header file inclusion model | Published as a TS |
Modules v2 | Improvements to Modules v1, including a better transition path | On track to be merged into C++20 |
Numerics TS | Various numerical facilities | Under active development |
Graphics TS | 2D drawing API | Future uncertain |
Reflection TS | Static code reflection mechanisms | PDTS ballot underway; publication expected in early 2019 |
A few links in this blog post may not resolve until the committee’s post-meeting mailing is published (expected any day now). If you encounter such a link, please check back in a few days.
Introduction
A few weeks ago I attended a meeting of the ISO C++ Standards Committee (also known as WG21) in San Diego, California. This was the third committee meeting in 2018; you can find my reports on preceding meetings here (June 2018, Rapperswil) and here (March 2018, Jacksonville), and earlier ones linked from those. These reports, particularly the Rapperswil one, provide useful context for this post.
This meeting broke records (by a significant margin) for both attendance (~180 people) and number of proposals submitted (~270). I think several factors contributed to this. First, the meeting was in California, for the first time in the five years that I’ve been attending meetings, thus making it easier to attend for Bay Area techies who weren’t up for farther travels. Second, we are at the phase of the C++20 cycle where the door is closing for new proposals targeting to C++20, so for people wanting to get features into C++20, it was now or never. Finally, there has been a general trend of growing interest in participation in C++ standardization, and thus attendance has been rising even independently of other factors.
This meeting was heavily focused on C++20. As discussed in the committee’s standardization schedule document, this was the last meeting to hear new proposals targeting C++20, and the last meeting for language features with significant library impact to gain design approval. A secondary focus was on in-flight Technical Specifications, such as Library Fundamentals v3.
To accommodate the unprecedented volume of new proposals, there has also been a procedural change at this meeting. Two new subgroups were formed: Evolution Incubator (“EWGI”) and Library Evolution Incubator (“LEWGI”), which would look at new proposals for language and library changes (respectively) before forwarding them to the Evolution or Library Evolution Working Groups (EWG and LEWG). The main purpose of the incubators is to reduce the workload on the main Evolution groups by pre-filtering proposals that need additional work before being productively reviewed by those groups. A secondary benefit was to allow the attendees to be spread out across more groups, as otherwise EWG and LEWG would have likely exceeded their room capacities.
C++20
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 Rapperswil report.
- Language:
- Abbreviated function templates (AFTs). After years of design iteration, AFTs finally gained consensus and will be shipped as part of C++20 along with the rest of Concepts. I discuss the consensus design below.
- Improvements to return-type-requirements.
- Immediate functions. These are functions that can only be called during constant evaluation (i.e. at compile time).
std::is_constant_evaluated()
try
/catch
blocks inconstexpr
functions.- Allowing
dynamic_cast
and polymorphictypeid
in constant expressions. - Changing the active member of a union inside
constexpr
char8_t
: a type for UTF-8 characters and strings.- Access control in contract conditions.
- Revising the C++ memory model. I’m not very familiar with this topic, but concurrency experts tell me this is long in the making and a rather important change.
- Weakening release sequences.
- Nested inline namespaces
- Signed integers are two’s complement
- Library:
- The most notable addition at this meeting was merging the Ranges TS into C++20!
- Fixing
operator>>(basic_istream&, CharT*)
.
variant
andoptional
should propagate copy/move triviality.
visit<R>
: explicit return type forvisit
.
<chrono>
zero()
,min()
, andmax()
should benoexcept
.
constexpr
instd::pointer_traits
.
- Miscellaneous
constexpr
bits.
unwrap_ref_decay
andunwrap_reference
reference_wrapper
for incomplete types
- A sane
variant
converting constructor
std::function
move constructor should benoexcept
std::assume_aligned
- Smart pointer creation with default initialization
- Improving completeness requirements for type traits)
- Remove
CommonReference
requirement fromStrictWeakOrdering
(a.k.a fixing relations)
- Utility functions to implement uses-allocator construction
- Should
span
beRegular
?
- Make stateful allocator propagation more consistent for
operator+(basic_string))
- Simplified partial function application
- Heterogeneous lookup for unordered containers
- Adopt consistent container erasure from Library Fundamentals v2
Technical Specifications
In 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 committee iterated on a number of TSes under development.
Reflection TS
The Reflection TS was sent out for its PDTS ballot at the last meeting. As described in previous reports, this is a process where a draft specification is circulated to national standards bodies, who have an opportunity to provide feedback on it. The committee can then make revisions based on the feedback, prior to final publication.
The PDTS ballot is still ongoing, so there wasn’t much to do on this front at this meeting. We expect the ballot results to be ready by the next meeting (February 2019, in Kona), at which time we’ll address the ballot comments and, time permitting, approve the revised TS for publication.
One minor snafu discovered at this meeting is that prior to the PDTS ballot, the Reflection TS, which depends on Concepts, has been rebased onto C++20, to take advantage of C++20 Concepts (previously, it was based on the Concepts TS). Unfortunately, ISO rules don’t allow publishing a TS before its base document is published, which means that to publish the Reflection TS as-is, we’d have to wait to do it concurrently with the C++20 publication in late 2020. We very much don’t want to wait that long, since the purpose of the Reflection TS is to gather feedback from users in preparation for revised Reflection features in C++23, and the earlier we start getting that feedback, the better. So, we’ll have to un-rebase the Reflection TS onto {C++17 + Concepts TS} to be able to publish it in early 2019 as planned. Isn’t red tape fun?
Library Fundamentals TS v3
This third iteration (v3) of the Library Fundamentals TS is open for new features to be added. (The TS working draft currently contains features from v2 which haven’t been merged into the C++ IS yet.) The only changes voted in at this meeting were a rebase and some issue resolutions, but a number of new features are on the way.
Executors
As discussed below, the revised plans for Executors are for a subset of them to target C++20, and the rest C++23. An Executors TS is not planned at this time.
Merging Technical Specifications into C++20
Turning now to Technical Specifications that have already been published, but not yet merged into the IS, the C++ community is eager to see some of these merge into C++20, thereby officially standardizing the features they contain.
Ranges TS
The Ranges TS modernizes and Conceptifies significant parts of the standard library (the parts related to algorithms and iterators), as well as introducing exciting new features such as range views.
After years of hard work developing these features and going through the TS process, the Ranges TS was finally merged into C++20, paving the way for wider adoption of these features.
Concepts TS
The approval of abbreviated function templates for C++20 at this meeting can be thought of as completing the merge of the Concepts TS into C++20: all the major features in the TS have now been merged, with some design modifications inspired by implementer and user feedback.
While the journey took longer than was initially hoped, in my opinion Concepts is a better feature for the design changes made relative to the Concepts TS, and as such this is an example of the TS process working as intended.
Modules TS
Modules remains one of the most highly anticipated features by the C++ user community. This meeting saw really good progress on Modules: a “merged” Modules design, combining aspects of the Modules TS and the alternative Atom proposal, gained design approval for C++20.
This outcome exceeded expectations in that previously, the merged proposal seemed more likely to target a Modules TS v2 or C++23, with a subset possibly targeting C++20; however, thanks in significant part to the special one-off Modules-focused Bellevue meeting in September, good enough progress was made on the merged design that the authors were comfortable proposing putting the entire thing into C++20, which EWG subsequently approved.
As this is a large proposal, wording review by the Core Working Group will take some time, and as such, a plenary vote to merge the reviewed wording into the C++20 working draft won’t take place until the next meeting or the one after; however, as all the major compiler implementers seem to be on board with this design, and there is overwhelming demand for the feature from the user community, I expect smooth sailing for that vote.
In fewer words: Modules is on track for C++20!
Coroutines TS
The Coroutines TS was once again proposed for merger into C++20 at this meeting. This is the third time this proposal was made (the other two times being at the previous two meetings). At the last meeting, the proposal got as far as a plenary vote at the end of the week, which narrowly failed.
The opposition to merging the TS into C++20 comes from the fact that a number of people have concerns about the Coroutines TS design (some of them are summarized in this paper), and an alternative proposal that addresses these concerns (called “Core Coroutines”) is under active development. Unfortunately, Core Coroutines is not sufficiently-baked to make C++20, so going with it would mean delaying Coroutines until C++23. Opinions differ on whether this is a worthwhile tradeoff: the Core Coroutines authors are of the view that C++ will remain a relevant language for 50 years or more, and waiting 3 years to improve a feature’s design is worthwhile; others have made it clear that they want Coroutines yesterday.
After the failure of last meeting’s merger proposal, it was hoped that waiting one more meeting would allow for the Core Coroutines proposal to mature a bit. While we knew it wouldn’t be ready for C++20, we figured the added maturity would allow us to better understand what we would be giving up by merging the Coroutines TS into C++20, and possibly identify changes we could make the Coroutines TS before C++20’s publication that would make incremental improvements inspired by Core Coroutines backwards-compatible, thereby allowing us to make a more informed decision on the C++20 merger.
Core Coroutines did make significant progress since the last meeting: the updated proposal is simpler, more fleshed out, and has a cleaner syntax. The impasse has also inspired efforts, led by Facebook, to combine the two proposals in such a way that would unblock the merger into C++20, and allow for backwards-comaptible improvements achieving many of the goals of Core Coroutines in C++23, but these efforts are at a relatively early stage (a paper describing the combined design in detail was circulated for the first time while the meeting was underway).
Ultimately, waiting a meeting doesn’t seem to have changed many people’s minds, and we saw a replay of what happened in Rapperswil: EWG narrowly passed the merger, and plenary narrowly rejected it; interestingly, the level of consensus in plenary appears to have decreased slightly since Rapperswil.
To keep C++20 on schedule, the final deadline for approving a TS merger is the next meeting, at Kona. The merger will undoubtedly be re-proposed then, and there remains some optimism that further development of Facebook’s combined proposal might allow us to gain the required confidence in a future evolution path to approve the merger for C++20; otherwise, we’re looking at getting Coroutines in C++23.
Networking TS
It’s looking like the Networking TS will not be merged into C++20, in large part due to the concerns presented this paper discussing usage experience. The TS will instead target C++23.
Evolution Working Group
With the increased number of subgroups meeting in parallel, it’s becoming more challenging to follow what goes on in the committee.
I usually sit in EWG for the duration of the meeting, and summarize the design discussions that take place in that group. I will try to do so again, but I did miss some EWG time while sitting in some study group meetings and Evolution Incubator meetings, so expect some reduction in the amount of detail. If you have specific questions that I didn’t cover, feel free to ask in the comments.
This time, I’ll categorize proposals by topic. For your convenience, I still indicate whether each proposal was approved, had further work on it encouraged, or rejected. Proposals are targeting C++20 unless otherwise mentioned.
Concepts
The headline item here is the approval of the compromise design for abbreviated function templates (AFTs). With this syntax, AFTs look like this:
void f(Concept auto x);
This makes both the “I want to write a function template without the template<...>
notation” and the “I want to be able to tell syntactically if a function is a template” camps happy (the latter because the auto
tells you the parameter has a deduced type, and therefore the function is a template).
You can also use Concept auto
as a return type, and as the type of a variable. In each case, the type is deduced, and the deduced type has to satisy the concept. The paper as written would have allowed the return type and variable cases to omit the auto
, but this didn’t have consensus and was removed.
Note that you can write just void f(auto x);
as well, making functions consistent with lambdas which could already do this.
Finally, as part of this change, a restriction was imposed on the template <Concept T>
notation, that T
has to be a type. For non-type and template template parameters, constraints can only be specified using a requires-clause. The motivation here is to be able to tell syntactically what type of entity T
is.
A few other Concepts-related proposals were looked at:
- (Further work) How to make terse notation soar with class template argument deduction. The idea here is to combine class template argument deduction (CTAD) and Concepts such that a class template name (e.g.
tuple
) can be used as a parameter type as if it were a concept (with the concept being, roughly, “this type is a specialization oftuple
“). The proposal was generally well-received, but there are some technical details to iron out, and design alternatives to consider (e.g. spelling ittuple<auto...>
), so this will be revisited for C++23. - (Rejected) A simple proposal for unifying generic and object-oriented programming. This is a more ambitious proposal to try to allow writing code that works with a set of polymorphic types, that looks the same regardless of whether the polymorphism is dynamic (inheritance) or static (concepts). Reception was mixed; some felt this would introduce a new programming model with relatively little benefit.
- (Rejected) Concept-defined placeholder types. This would have allowed defining a “placeholder type” constained by a concept, and using that type in place of the concept. It didn’t really fit with the AFT design that was approved.
- (Rejected) Multi-argument constrained parameter. This proposed a whitespace-based syntax for introducing multiple constrained parameters in a template parameter list, e.g.
template <EqualityComparableWith T U>
. EWG didn’t feel the whitespace syntax was an improvement over other syntaxes that have been rejected, liketemplate <EqualityComparableWith{T, U}>.
EWG ran out of time to review the updated “constraining Concepts overload sets” proposal. However, there was some informal speculation that the chances of this proposal making C++20 have diminished, because the proposal has grown a lot more complex in an attempt to address EWG’s feedback on the previous version, which suggests that feedback had touched on some hard problems that we may not be in a good position to solve at this time.
Modules
As mentioned, perhaps the biggest high-point of this meeting was EWG’s approval of the merged Modules design for C++20. “Merged” here refers to the proposal combining aspects of the Modules TS design, and the alternative Atom proposal. Perhaps most significantly, the design borrows the Atom proposal’s legacy header imports feature, which is intended to better facilitate incremental transition of existing large codebases to Modules.
Several minor modifications to this design and related changes were also proposed:
- (Approved) Making
module
a context-sensitive keyword, take two. Following consistent feedback from many segments of the user community that makingmodule
a hard keyword would break too much code, a new proposal for making it context-sensitive, this time with simpler disambiguation rules, was approved. - (Approved) Single-file modules with the Atom semantic properties rule. This allows module authors to do certain things that previously required separate module partitions in separate files, in one file.
- (Approved) Module preamble is unnecessarily fragile. This tweaks the rules for where a module file’s “preamble” (the area containing the module declaration and imports) ends, with a view to making the user model simpler.
- (Approved) Redefinitions in legacy imports. This clarifies some of the rules in scenarios involving legacy header imports.
- (Further work) Modules and freestanding. This mostly has to do with how to split the standard library into modules, with the relevance to EWG being that we should have a consistent approach for dealing with freestanding implementations in the language and in the library. EWG did not reach a consensus on this topic, mostly because there are a wide variety of freestanding environments with different constraints, and a single subset of the language does not fit all of them.
- (Further work) Inline module partitions. This is a generalization of “Single-file modules with the Atom semantic properties rule”, which would allow defining an arbitirary number of module partitions “inline” in a single file. EWG encouraged further development of this idea, but for post-C++20.
- (Rejected) Global module fragment is unnecessary. The global module fragment is one of two mechanisms for transitioning existing code to Modules (the other being legacy header imports). The author of this paper suggested that just legacy header imports may be sufficient, but this was emphatically argued against based on implementation experience at some companies, leading to the proposal’s rejection.
- (Rejected) Retiring pernicious language constructs in module contexts. This paper suggested that Modules was an opportunity to shed some of the language’s legacy cruft by making certain constructs invalid inside a module (while they would remain valid in non-modular code for backwards compatibility). There wasn’t much enthusiasm for this idea, largely because it’s expected that people will want to be able to freely copy / migrate code from a non-modular context to a modular context and vice versa.
Contracts
- (Approved) Access control in contract conditions. This was the subject of a very long and drawn-out debate on the committee mailing lists which I won’t attempt to summarize, but the outcome was that pre- and post-conditions on member functions can reference private and protected variables inside the class, even though we think of them as being part of the class’s public interface.
- (Approved) Contract postconditions and return type deduction. This is a tweak regarding the interaction between postconditions and return type deduction, with the intention to avoid surprising behaviour. Option 3 from the paper had consensus.
- (Further work) Allowing contract predicates on non-first declarations. EWG was open to this idea, but some implementation issues (such as who emits the code for the contract check) need to be ironed out.
- (Further work) Undefined behaviour in contract violations. This was another topic that engendered very extensive mailing list discussion. No decision was made this week, but the likely direction is to specify that contracts (except perhaps
axiom
s) do not allow compilers to assume additional things they couldn’t already assume. - (Rejected) Contracts updates. Of the three minor changes proposed in this paper, the first was a trivial wording change (which was approved); the second had no consensus; and the third was deemed unimplementable.
constexpr
Continuing with the committee’s concerted effort to make clunkier forms of compile-time programming (such as template metaprogramming) unnecessary, EWG approved further extensions to constexpr
:
- (Approved) Allowing
dynamic_cast
and polymorphictypeid
in constant expressions - (Approved) Make
std::typeinfo::operator=
constexpr
- (Approved) A tweak to immediate functions. The keyword used to introduce them was changed from
constexpr!
toconsteval
because the former presented lexical concerns. - (Further work) Expansion statements. These can be thought of compile-time
for
loops; they were previously proposed as tuple-basedfor
loops. They’re called expansion statements because they are expanded (unrolled) at compile time, with the body of each “iteration” potentially working with different types. The current proposal contains two forms,for ...
andfor constexpr
, and EWG expressed a desire to unify them.
Coroutines
I mentioned above that EWG narrowly passed the latest version of a proposal to merge the Coroutines TS into C++20, only to have it rejected in a plenary vote.
The technical discussion of this topic centred around an updated version of the competing Core Coroutines proposal, and a paper by Facebook engineers arguing that most of the benefits of Core Coroutines could be achieved through extensions to the Coroutines TS, and we should therefore go ahead with the Coroutines TS in C++20.
An interesting development that emerged mid-meeting is the Facebook folks coming up with a “unified coroutines” proposal that aims to achieve consensus by combining aspects of the two competing proposals. There wasn’t really enough time for the committee to digest this proposal, but we are all hopeful it will help us make an informed final decision (final for C++20, that is) at the next meeting.
Structured Bindings
- (Approved in part) Extend structured bindings to be more like variable declarations. Structured bindings can now be
static
,thread_local
, orconstexpr
; in each case, this applies to the entire composite object being destructured. Rules around linkage were also clarified. Capture of bindings by a lambda was deferred for further work. - (Further work) Simplify the customization point for structured bindings. EWG wholehearted wants an overhaul of the customization point (the current one just piggybacks on the customization point for tuple-like that we already had in the language), but felt this proposal addressed just one piece of what is a larger puzzle. A more complete proposal may look something like the
operator extract
from an earlier pattern matching proposal. - (Rejected) Structured bindings with explicit types. This was rejected because the use cases will be addressed more comprehensively with pattern matching.
Class Template Argument Deduction (CTAD)
- (Approved in part) Filling holes in class template argument deduction. CTAD now works with aggregates, alias templates, and inheriting constructors. Making CTAD work with partial template argument lists was rejected because it would be a breaking change in some cases (e.g. consider
vector<any>(MyAlloc())
). - (Rejected) Improving function templates with CTAD. EWG found that this would involve a lot of complexity, since with function templates you don’t just have one template definition as with class templates, but a whole overload set.
Comparisons
Most comparison-related proposals involved early adopters trying out the spaceship operator (<=>
) and discovering problems with it.
- (Approved) I did not order this! Why is it on my bill?, which probably deserves a medal of some sort for most creative paper title. (Explanation: the paper concerns scenarios where you don’t care about ordering your type, only equality-comparing it, you implement a defaulted
operator<=>
(because that’s “the C++20 way” for all comparison use cases), and you pay a performance penalty that wouldn’t be there with hand-written code to deal with equality comparison only.) A related paper offers a solution, which is along the lines of making==
be its own thing and not fall back to using<=>
, since that’s where the inefficiency stems from (for types likestring
, if the lengths are different you can answer “not equal” much faster than if you’d have to answer “less” or “greater than”). A second part of the proposal, where a defaulted<=>
would also generate a defaulted==
, so that users can be largely oblivious to this problem and just default one operator (<=>
), was more controversial, but was still approved over some objections. - (Approved) When do you actually use
<=>
? The crux of this paper is that we’ve had to invent a library functioncompare_3way()
wrapping<=>
and that’s what we want to use most of the time, so we should just give<=>
the semantics of that function. - (Mooted)
weak_equality
considered harmful. This proposal has become moot as implementations of==
are no longer generated in terms of<=>
. (As a result,weak_equality
andstrong_equality
are no longer used and will likely be removed in the future.) - (Rejected) Chaining comparisons. Despite previous encouragement, this was now rejected due to concerns about teachability and implementation issues.
Other New Features
- (Further work) Deducing
this
. This proposal allows writing member functions where the type ofthis
is deduced, thereby eliminating the need to duplicate implementations for things likeconst
vs. non-const
objects, and other sources of pain. There was a fair amount of technical discussion concerning recursive lambdas (which this proposal hopes to enable), name lookup rules, and other semantic details. The authors will return with a revised proposal. - (Rejected) Towards a lazy forwarding mechanism for C++. This would allow declaring function parameters to be “lazy”, such that their arguments are evaluated upon their use inside the function (and possibly not at all if there is no use), rather than at the call site; participants pointed out a similarity to Algol’s “call by name” feature. EWG wasn’t categorically opposed to the notion of lazy parameters, but the notion of having them without any call-site syntax (like this paper proposes) was controversial.
Bug / Consistency Fixes
(Disclaimer: don’t read too much into the categorization here. One person’s bug fix is another’s feature.)
- (Approved) Allow initializing aggregates from a parenthesized list of values. This finally allows things like
vector::emplace_back()
to work for aggregates. - (Approved) Contra CWG DR1778. This has to do with
noexcept
and explicitly defaulted functions. The first option from the paper was approved. - (Approved) Permit conversions to arrays of unknown bound. The motivation cited for this is working in environments where dynamic allocation is not allowed and use of pointers is restricted, and thus passing around variable-length arrays as arrays of unknown bound are the only way to work with dynamically sized data ranges.
- (Approved) Array size deduction in new-expressions. This is a minor consistency fix that was also approved as a Defect Report against older language versions.
- (Approved) Nested inline namespaces. This allows using the C++17 nested namespace syntax in cases where one or more of the namespaces are inline. Example:
namespace foo::inline bar::baz { }
is short fornamespace foo { inline namespace bar { namespace baz { }}}
.inline
is not allowed in the leading position as people might mistakenly think it applies to the innermost namespace. - (Further work) Conditionally trivial special member functions. This is a small but important fix for library implementers who would otherwise have to use labour-intensive techniques to meet the triviality requirements set out for standard library types. This was essentially approved, but specification difficulties necessitate one more round of review.
- (Further work) Ultimate copy elision. This aims to expand the set of scenarios in which the compiler is allowed to elide copies and moves (note: unlike the C++17 “guaranteed copy elision” feature, this is not requiring compilers to elide copies in these new scenarios, just allowing them). EWG liked the general idea but had concerns about the potential for code breakage in some scenarios.
- (Further work) Adding the
[[constinit]]
attribute. The motivation here is cases where you want to guarantee that a variable’s initial value is computed at compile time (so no dynamic initialization required), without making the variableconst
(so that you can assign new values to it at runtime). EWG liked the idea but preferred using a keyword rather than an attribute. An alternative to decorate the initializer rather than the variable had no consensus. - (Postponed)
short float
. This proposal continues to face challenges due to concerns about different implementations using different sizes for it, or even different representations within the same size (number of bits in mantissa vs. exponent). As a result, there was no consensus for moving forward with it for C++20. There remains strong interest in the topic, so I expect it will come back for C++23, possibly under a different name (such asfloat16_t
instead ofshort float
, to specify the size more concretely). - (Rejected) Deprecate the addressof operator. This proposes to deprecate the overloading of
operator &
. EWG didn’t feel that removal was realistic given that we don’t have a good handle on the breadth of usage in the wild, and didn’t want to entertain deprecation without an intention to remove as a follow-up.
Evolution Working Group Incubator
As mentioned above, due to the increased quantity of proposals, an “EWG Incubator” group (EWGI) was also spun up to do a preliminary round of review on some proposals that EWG couldn’t get to this week, in the hope of making them better-baked for their eventual EWG review at a future meeting.
I only attended EWGI for half a day, so I don’t have much to report about the discussions that went on, but I will list the papers the group forwarded to EWG:
- Make
char16_t
/char32_t
string literals be UTF-16/32 - Named character escapes
using enum
nodiscard
should have a reason
There were also a couple of papers EWGI referred for EWG review not necessarily because they’re sufficiently baked, but because they would benefit from evaluation by a larger group:
Numerous other proposals were asked to return to EWGI with revisions. I’ll call out a couple:
- There were two proposals for pattern matching. The feature had strong support, and the authors were asked to return with a combined proposal.
- There was another attempt at named arguments (called “labelled parameters” in the proposal). The novelty in this approach was putting the names in the type system, but without actually modifying any semantic rules like overload resolution, by encoding the labels using existing mechanisms in the type system, and then layering a “sugar” syntax on top. EWGI’s feedback was that the attempted abstraction will leak, and we’ll have to end up making deeper modifications to the type system after all, to have a usable feature. Encouragement to return was weak but existent.
Papers not discussed
There were, of course, also papers that neither EWG nor EWGI had the time to look at during this meeting; among them was Herb’s static exceptions proposal, which is widely anticipated, but not targeting C++20.
I’ll also briefly mention the lifetimebound
proposal which Mozillians have expressed a particular interest in due to the increased lifetime safety it would bring: the authors feel that Microsoft’s lifetime checker, whose model of operation is now described in a paper is doing an adequate job of satisfying this use case outside of the core language rules (via annotations + a separate static checker). Microsoft’s lifetime checker ships with MSVC, and has a work-in-progress implementation in Clang as well, which can be tried out in Compiler Explorer, and will hopefully be open-sourced soon. See also Roc’s blog post on this subject.
Other Working Groups
Library Groups
Having sat in the Evolution groups, I haven’t been able to follow the Library groups in any amount of detail, but I’ll call out some of the more notable library proposals that have gained design approval at this meeting:
std::span
changes: notRegular
, utility enhancements- Merging portions of the Library Fundamentals TS:
to_array()
,resource_adaptor
- Text formatting
- A stack trace library
- An “omnibus” synchronization proposal that includes efficient atomic waiting and semamphores, latches and barriers, and
atomic_flag::test
and lock-free integral types. With this, the only portion of the Concurrency TS v1 that isn’t headed for C++20 in some form isfuture.then()
, which is still to come (no pun intended). - A polymorphic value-type
- A resolution to the debate of whether
size()
should be signed or unsigned: it will be unsigned, and a newstd::ssize()
free function will be added which will return a signed type.
And a few notable proposals which are still undergoing design review, and are being treated with priority:
- More things from the Library Fundamentals TS:
source_location
- Ranges enhancements and integration: input range adaptors, range constructors for standard containers and views
- Monadic operations for
std::optional
- Executors, with the “properties API” portion pulled out into a separate proposal
- Safe integral comparisons
flat_set
jthread
(cooperatively interruptible joining thread)- Optimized initialization for
basic_string
(notvector
for now)
There are numerous other proposals in both categories above, I’m just calling out a few that seem particularly noteworthy. Please see the committee’s website for a full list of proposals.
Study Groups
SG 1 (Concurrency)
Most of the C++20-track work (jthread
, Executors subset, synchronization omnibus paper, memory model fixes) has progressed out of the Concurrency Study Group and is mentioned above.
For Executors, the current plan is to put a subset of the unified proposal (specifically including “one way” and “bulk one way” executors, but not the other kinds) into C++20, and the rest into C++23; a TS is not planned at this time.
Coroutines-related library additions are not being reviewed yet; they need more bake time, and integration with the next revision of Executors.
SG 1 has opinions on freestanding implementations: they feel omitting thread_local
from a freestanding implementation is fine, but omitting non-lock-free atomics or thread-safe statics is more controversial.
SG 7 (Compile-Time Programming)
There were two meetings related to compile-time programming this week. The first was an evening session where the committee re-affirmed its preference for constexpr-based metaprogramming as the future of C++ metaprogramming, in preference to template metaprogramming (TMP). (There was some confusion in this regard, as there was a proposal to standardize Boost.Mp11, a TMP library. The feeling at the end of the meeting was that with constexpr metaprogramming just around the corner, it’s probably not the best use of committee time to standardize a TMP library.)
The second was an afternoon meeting of SG 7, where the main agenda item was reviewing two proposals for reflection based on constexpr metaprogramming: constexpr reflexpr
, and scalable reflection in C++. The first is by the authors of the Reflection TS, and tries to carry over the Reflection TS facilities to the land of constexpr in a relatively straightforward way. The second is a variation of this approach that reflects experience gained from experimentation by some implementers. Both proposals also go further than the Reflection TS in functionality, by supporting reification, which involves going from meta-objects obtained via reflection back to the entities they represent.
One notable difference between the two proposals is that the first uses meta-objects of different types to represent different kinds of entities (e.g. meta::variable
, meta::function
, etc.), whereas the second uses just one type (meta::info
) for all meta-objects, and requires using operations on them (e.g. is_variable()
) to discriminate. The authors of the second proposal claim this is necessary for compile-time performance to be manageable; however, from an interface point of view the group preferred the different-types approach, and some implementers thought the performance issues could be solved. At the same time, there was agreement that while there should be different types, they should not form an inheritance hierarchy, but rather be type-erased by-value wrappers. In addition, the group felt that errors should be visible in the type system; that is, rather than having meta-objects admit an invalid state, reflection operations that can fail should return something like expected<meta::info>
instead.
The target ship vehicle for a constexpr-based reflection facility is not set in stone yet, but people are hopeful for C++23.
In addition, SG 7 approved some guidelines for what kinds of library proposals should require SG 7 review.
SG 13 (Human/Machine Interface)
The Human/Machine Interface Study Group (SG 13) deals with proposals for graphics, event handling, and other forms of user interaction.
Its main product so far has been the 2D graphics proposal, which had been making good progress until it lost consensus to move forward at the last meeting. As there was still significant interest in this proposal in many user communities (see e.g. this paper arguing strongly for it), the Convenor asked SG 13 to have another look at it, to see if consensus could somehow be re-attained. There wasn’t extensive technical discussion of the proposal at this meeting, but we did go over some feedback from potential implementers; it was suggested that the author and other interested parties spend some time talking to graphics experts, many of whom are found in the Bay area (though not the ones at Mozilla – our graphics folks are mostly in the Toronto office).
The group also discussed the web_view
proposal, which was positioned as an alternative to rolling our own graphics API. As the proposal effectively involves shipping a web platform implementation as part of the C++ standard library, this proposal has a lot of relevance to Mozilla. As such, I solicited feedback on it on Mozilla’s platform mailing list, and the feedback was pretty universally that this is not a good fit for the C++ standard library. I relayed this feedback at this meeting; nonetheless, the group as a whole was in favour of continuing to pursue this proposal. In fact, the group felt this and 2D graphics serve different use cases and should both be pursued in parallel. (Admittedly, there’s some selection bias going on here: people who choose to attend a meeting of SG 13 are naturally likely to be in favour of proposals in this topic area. I’m curious to see how these proposals will fare in front of a larger voting audience.)
There was also some general discussion of other topics in scope for this group. There are plans for bring forward a proposal for an audio API, and there were also ideas thrown around about things like event handling, user input, sensors, and VR.
SG 15 (Tooling)
The Tooling Study Group (SG 15) met for an evening session, and numerous papers concerning a variety of topics were presented.
The most pressing topic was how to integrate Modules with build systems. The problem is nicely summarized in this paper, and proposed solutions range from a separate “module mapper” component to relying on conventions.
The other major topic was general discussion about where to go in the space of dependency and package management. Ideas presented here include a set of APIs to allow components of a package ecosystem to interface with each other without requiring a particular implementation for any one component, and ideas around package specification.
I don’t feel like a lot of decisions were made in this session, and the group as a whole seems to be conflicted about what its role is given that these areas are not in the purview of the C++ standards document itself, but I still think the evening served as a valuable opportunity for pioneers in these areas to exchange areas and build mindshare around the tooling problems facing the C++ community.
Other Study Groups
Other Study Groups that met at this meeting include:
- SG 6 (Numerics), which met for about a day and a half and reviewed a dozen or so proposals
- SG 12 (Undefined and Unspecified Behaviour), which met both on its own (largely due discuss Contracts) and in joint session with WG23 – Software Vulnerabilities (where the focus was on vulnerabilities related to control structures)
- SG 16 (Unicode), for which this was the first in-person meeting. The group approved a set of high-level priorities in addition to reviewing several specific proposals.
Freestanding Implementations
Not a study group, but this didn’t really fit anywhere else: there was an evening session to try to clarify the committee’s approach to freestanding implementations.
Freestanding implementations are, roughly speaking, those which cannot assume the presence of a full complement of operating system services, because they’re e.g. targeting kernel code or other “bare metal” scenarios; such implementations cannot practically make use of all language features, such as exceptions.
The standard currently defines a subset of the library that is intended to be supported on freestanding implementations, but defines no such subset for the language. Attempts to define such a subset tend to be stymied by the fact that different environments have different constraints, so one subset does not fit all.
The session didn’t reach any firm conclusions, but one possible direction is to avoid trying to define subsets, and instead make it easier for target environments to not use features of the language that are not applicable or practical for it.
New Study Groups
Two new Study Groups were announced at this meeting. Quoting their charters from Herb Sutter’s trip report:
SG 19 (Machine Learning):
We feel we can leverage C++’s strengths in generic programming, optimization and acceleration, as well as code portability, for the specific domain of Machine Learning. The aim of SG19 is to address and improve on C++’s ability to support fast iteration, better support for array, matrix, linear algebra, in memory passing of data for computation, scaling, and graphing, as well as optimization for graph programming.
SG 20 (Education):
We feel we have an opportunity to improve the quality of C++ education, to help software developers correctly use our language and ecosystem to write correct, maintainable, and performing software. SG20 aims to create curriculum guidelines for various levels of expertise and application domains, and to stimulate WG21 paper writers to include advise on how to teach the new feature they are proposing to add to the standard.
Next Meetings
The next meeting of the Committee will be in Kona, Hawaii, the week of February 18th, 2019.
Conclusion
C++ standards development continues to progress at an unprecedented pace. My highlights for this meeting included:
- Modules gaining design approval to go into C++20
- Abbreviated function templates reaching consensus, to round out Concepts in C++20
- Ranges being voted into the C++20 working draft
- Coroutines continuing to progress towards a unified design that can hopefully achieve consensus
With the big-ticket items above, not to mention Contracts, operator spaceship, and many other goodies, C++20 is shaping up to be a very impressive release!
Due to 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
In addition to Herb’s, other trip reports about this meeting include Corentin Jabot’s, a collaborative Reddit report, and a podcast focused on Library Evolution by Ashley Hedberg. I encourage you to check them out as well!