February 28, 2019

Kona: A trip report

I was lucky enough to participate in a third wg21 committee meeting in a row, this time in Kona, Hawaii, a mere 13000 kilometers away.

Kona

As is tradition, Bryce and others wrote a rather thorough trip report on Reddit and you should check it out. However, if you want to read more details about my experience and some of the proposals I find important, please read on (knowing that your time is limited, and doing so will leave less time to read other blog posts).

With a handful of active study groups, 2 incubator groups, Evolution, Library Evolution, Core Wording Group, and Library Wording Group, it is impossible to follow closely everything that happened in the 7 or so concurrently running rooms. As such, I missed discussions about some proposals I have strong opinions about and participated in discussions about features I feel strongly neutral about.

Such is life.

I also reserve the right not to have an opinion on the basis that on most topics, I’m too stupid to have an informed one.

And the committee is by no mean slowing down. The pre-Kona mailing list have a staggering 177 papers. Including 144 never-seen-before papers. This meeting was also the feature freeze for C+20. Which means no feature not approved by an evolution group before the end of the meeting will be added in C++20. At least, that’s the theory.

This meeting has been described as being historic and indeed we approved a lot of major features that have been in the work for a while as well as a number of small quality of life improvements. C++20 is poised to be the biggest release since C++11, or, dare I say it, _ever _?

The number of features actually added this meeting was relatively small, but a lot of papers are waiting to go through the wording groups and should be accepted in Cologne.

Coroutines

Coroutines were merged with a very strong consensus and I think this is terrific. If you follow the development of C++ closely, you would have noticed that their design has not changed significantly over the past year, but there was no consensus to merge them in San Diego or Rapperswil. So, why now?

One contention point of the Coroutines TS is that it always heap-allocate the type-erased coroutine frame and relies on impressive optimization techniques to make these allocations disappear when the frame does not outlive the caller’s context.

The Core Coroutine proposal offered deterministic stack allocations of coroutines frames.

The issue with having the coroutine frame allocated on the stack is that it can not be optimized away without black magic. That black magic now has a name: Deferred layout. A seducing idea that would let the compiler backend set the layout of some types including coroutine frames. We would then be to optimize away stack allocated coroutines. However, these types would not have a constexpr sizeof which has deep-reaching consequences in the language and more importantly is deemed very complex to implement by compiler vendors (ie, it would probably cost a few tens of millions of dollars in R&D accross the industry to get there) This idea then is very much an area of research that might not bear fruit (or not) in the next 5 to 10 years. Deferred layout types would also not be able to cross TU boundaries, so some form of type erasure would still be needed.

So, what I think happened is that people realized that the core coroutines would not be implementable for a very long time, whereas the TS has been implemented in all compilers with great success. We are also confident - although not certain - that there is a way for coroutines to gain deterministic allocation in the future, in backward compatible fashion.

Coroutines then are not perfect, but they certainly good enough for an overwhelming majority of use cases. And they are so powerful and universally useful that it became quite apparent that it was not reasonable to deprive the community of coroutines while we chase after unicorns.

I would have like P1477 to be discussed, but it seems Evolution ran out of time. I really hope this can be discussed before C++20 as it makes writing new coroutine types more palatable. Note that writing coroutines types is not something we expect most C++ developers to ever needing to do.

Unfortunately, time has run out and C++20 will not ship with any standard library support for coroutines. I am afraid this will give people a bad impression of an otherwise amazing feature.

Consequently, I recommend that you use cppcoro when trying out and using coroutines as it hides the gory details and gives a good idea of what we expect the Standard library to offer in future versions of C++. This library is authored by Lewis Baker, who has greatly contributed to the success of coroutines.

Then there is the keywords mess, which I think is still important to address, but this is a loosing battle. (There will be a paper in the post-mailling which offer a great way to use await and yield as keyword without breaking any existing code - I really, really hope it will be given serious consideration !)

Overall, the merge of the core coroutines TS is an incredible success for C++ and Gor Nishanov who has been working on coroutines (or so-called Gorroutines) for the past 5 years.

Having coroutines in the standard open the door for a lot of proposals and work, for example

  • A user-friendly networking library
  • Well integrated executors
  • Sane implementation of Unicode bidirectional iterators

co_celebration

Modules

Modules too got merged into the IS with an extremely strong consensus. That too is a major transformational feature who has been in the work for more than a decade.

I voted against. Maybe I should explain why!

Modules have been branded as a paradigm shift. Which isn’t wrong. Modules might indeed be the most transformational feature C++ will gain in the coming decades. Which is why it is important to get them right.

But here is the thing. Modules are not stable. Not by a long shot. There have been papers written overnight (kudos to the authors !) during the meeting to fix issues with linkage of static symbols. The design changed considerably (for the better) over the past year.

There is no usage experience whatsoever with non-legacy modules as proposed by the merged proposal. (There is a lot of experience with legacy modules though.)

You would think for a feature that will have a profound impact on the whole ecosystem we would have taken the time to make sure modules do indeed work as intended and let the design mature for a while. We didn’t.

According to their proponents, modules fix everything, from componentization to ODR to compilation speed, but it is unknown how much code and build systems they will break. As someone said, the first import statement in a code base will be very costly. Expect pain and suffering over the next decade.

Critically, it will be hard (as in, close to impossible) to alter meaningfully the way modules work once the IS ships (unlike coroutines which have sufficient room to evolve).

A TR for the C++ ecosystem.

While working on deterministic module name mapping to file with Peter Bindels, it became apparent to me that we would never get to fix the toolability concerns of modules (as expressed in P1427 ) in the IS.

Jetlag helping, I started to draft some slides at 4 am the day of the tooling session. Later, a few SG-15 members and me stat down near the pool and thanks to Bryce Adelstein Lelbach we were able to present a call for a “C++ Ecosystem Technical Report” later that day.

We got a very positive reception.

The idea is to, alongside the IS, describe the common use case of source-file-to-machine-code compilation driven by a build system in a separate ISO document. We will first focus on making module workable and might be able to later extend this document to package management. And maybe even IPR. The document will strive to offer guidelines, inter-exchange formats and other specifications to offer all tools and compilers a common baseline to follow such that modularized code can be shared and reused in a wide variety of scenarios and platforms.

SG-15 will do its best to have enough material to ship a first version of this document in about the same time as the IS to ensure modules are a success, but it’s a tall order.

No standard library modules in C++20

The standard library will not be modularized in C++20 but standard libraries modules will be considered legacy header units, so #include <vector> will be equivalent to import <vector> while import std; will be ill-formed.

For some reason, we decided that it would be implementation-defined whether C headers would be legacy header units, and as such, import <stdlib.h>; might compile on your platform. Or not.

We realized that macros used to configure the standard library might stop working or break in fun and unexpected ways but that didn’t stop anything.

How broken are modules?

Modules are probably 90% of the way there. I think they could be ready in a few meetings.

Language-wise my main concern at this point is the inline keyword. Which makes absolutely no sense whatsoever in a module context (at least to me). I’ll try to detail why in a paper - time permitting - but I doubt there is still time to fix that. We will see I guess.

It remains to see how successful the TR approach will be as it will still require a lot of vendors to agree on specify behaviors that are currently implementation-defined.

I have also still huge concerns about what modules are not.

Implicit forward-declarations (hoisting) in module context was never seriously considered, the opportunity to clean up the language P0997 was shot down, the single-file module use-case was barely considered, etc. Yet, it seems that the wider community still expect modules to be

  • A name scoping mechanism (they are not)
  • A replacement to libraries (they are not)
  • A massive compilation speed improvement (they offer some improvement in some use-cases)
  • Portable (they are not)
  • A symbol versioning system (they are not)

I’m not sure everyone on the committee agrees on what modules are, nor should be but at least implementers all have their own interesting twist on how modules and BMI are implemented. But I was advised to be more positive so here are a few things I like about modules

  • They let you specify exactly what is and is not part of the public interface
  • They sandbox macros
  • They require module names to be unique - if done right this can help package managers.
  • They actually materialize the interface/implementation entities - if done right this can help package managers.
  • They are closed
  • They may help improve compilation speed in some common scenarios

The situation is certainly not as dire as I make it to be. Forgive me, I am a bit salty. Truth is, the consensus in plenary was strong enough that I’m probably wrong and regardless modules are still an incredible achievement by their authors and congratulations are in order.

We have still time to fix things and SG-15 will be meeting twice a month to do their best to make module adoption as smooth as possible. I think it’s great that SG-15 new charter is, for the time being, more focused and narrow as it will help the group progress in small steps towards where we want to be.

Towards Module adoption

My papers

One of the reasons I flew to the opposite side of the planet is that I accidentally wrote the most papers on the pre-Kona mailing. Sorry.

Deprecate uses of the comma operator in subscripting expressions

P1161

When they tell you to write papers, they don’t tell you would ultimately end up in core. It is a rather stressful experience, as I had to live edit-generate-upload my paper as wording experts were arguing about each word, each comma. Keeping track off all the changes requested as I was still trying to modifying the paper was definitively challenging.

It is, however, a necessary process as confusing wording is hardly implementable and the wording is, after all, the only product of WG21’s work. Ultimately, core was satisfied with the wording and P1161 should be voted in plenary in Cologne!

Now, the question remains as to how we can reclaim that syntax in the C++23 timeframe such that mdspan and linear algebra’s matrices can make use of it.

source_location

P1208

source_location is mostly the work of Robert Douglas, but I did manage to pull it out of Library Fundamentals and I fully expect it will be merged into the C++20 WD at the next meeting. LWG did a first review of the wording after the official adjournment of the meeting (which was less intense than core), and I will upload a more or less final version of the wording in the post mailing.

source_location API might change slightly before the publication of C++20 as we try to unify the interfaces of source_location , contract_violation and stacktrace

Movability of Single-pass Iterators

P1207

This paper proposes to strike the Copyability requirement for non-forward iterators, which is a small change with a rather big impact. I probably should do a separate blog post about it. I encourage you to read the paper, as I tried to motivate the design as much as possible.

I still have to provide full wording for it but LEWG approved the design and it should go in 20 if all goes well. I was really not expecting that this paper would receive as much support as it did and I’m incredibly grateful to all the people who helped me shape and simplify the design - the first iterations were rather terrible.

The basic idea is that objects non-forward iterators are used to iterate over are not regular and that consequently non-forward iterators should not require regularity either. In fact, I show that there is a relation between the notion of single-pass and that of non-copyability.

Practically speaking, this change permits the creation of non-forward iterators that are safer to use and easier to teach.

One of the reasons we are doing this change now and not before or later is that stadard concepts can never be changed at all as both relaxing a concept and adding requirement represent API breaks.

The new ranges concepts gave us a unique opportunity to better defined the requirements of iterators and we took it. I will have to iterate over the wording over the past few months and hopefully present LWG with something standard worthy before Cologne. I don’t really have a choice, do I?

There might be a few other tweaks before C++20 ships as it is important to get everything just right.

ranges::to

P1206

No, I haven’t proposed ranges 2.

P1206 was originally called “Range constructors for containers” but this approach was defeated by initializer_lists. So, I went back to the drawing board and came back with a design that was rather close to the existing ranges-v3’s to_ facility.

ranges::to works both as a function and a pipable object and can construct a container from a range (whether that is another container or a view). It supports standard containers, associative containers, extra parameters such as allocators and can deduce the type of the container’s value type.

std::list<int> l;
std::map<int, int> m;
// copy a list to a vector of the same type
auto a = ranges::to<std::vector<int>>(l);
//Specify an allocator
auto b = ranges::to<std::vector<int, Alloc>(l, alloc);
// copy a list to a vector of the same type, deducing value_type
auto c = ranges::to<std::vector>(l);
// copy to a container of types ConvertibleTo
auto d = ranges::to<std::vector<long>>(l);
//Supports converting associative container to sequence containers
auto f = ranges::to<vector<std::pair<const int, int>>>(m);
//Supports converting sequence containers to associative ones
auto g = f | ranges::to<map>();
//Pipe syntaxe
auto g = l | ranges::view::take(42) | ranges::to<std::vector>();
//Pipe syntax with allocator
auto h = l | ranges::view::take(42) | ranges::to<std::vector>(alloc);
//The pipe syntax also support specifying the type and conversions
auto i = l | ranges::view::take(42) | ranges::to<std::vector<long>>();
//Pathenthesis are optional
auto j = l | ranges::view::take(42) | ranges::to<std::vector>;
//and types
auto k = l | ranges::view::take(42) | ranges::to<std::vector<long>>;

This facility was accepted by LEWG and should be present in C++20 if LWG has the time to review the wording - that I haven’t written yet - in Cologne. A lot of work was done by Eric Niebler on this proposal, notably to make the paratheses optional. Minor implementation and design changes were made during the week, so expect a new revision in the post mailing list.

I think this function will prove extremely useful - especially to stick views (which are lazy) into memory.

Conceptify all the things

I proposed generalized ranges-based constructors constrained by ContiguousRanges to both std::span and std::string_view both of which were accepted - pending wording review, as always. This allows constructing span from views and string_view from, for example, a std::vector<char8_t> or a QByteArray - which was always the intent of string_view.

Tight integration

More peppers 🌶️

I still have a terrible French accent.

Anyhow.

Move-only views

P1456

Casey Carter proposed a paper for move-only views which was accepted, more or less for the same reasons move-only iterators were. An extra benefit of move-only views is that for example view_filter can support move-only predicates.

View all the things

P1035

You would have noticed that rounding-up the rangification of the STL is a common theme of these papers. P1035, authored by Christopher Di Bella is the biggest piece of that story, as it adds a number of views including

  • istream_view (view over an input stream)
  • take_while (view over the first elements of a range matching a predicate)
  • drop (view over the elements of a range, skipping the nth first elements)
  • drop_while (view over the elements of a range, skipping first elements matching a predicate)
  • keys (view over the first elements of a sequence of pairs)
  • values (view over the second elements of a sequence of pairs)
  • elements (view over the nths elements of a sequence of tuples)

Christopher was nice enough to let me add the last three views in his paper, although he ended up doing most of the wording work on it. Thanks Chris!

zip did not make the cut as it requires careful modifications of pair and tuple. enumerate was not proposed but requires the same modification of tuple as zip. We expect these very useful views to be offered in C++23.

The very best views

Integration of chrono with text formatting

P1361

Integration of chrono with text formatting authored by Victor Zverovich and Howard E. Hinnant, authors of std::format and <chrono> respectively, unifies the fmt and chrono API, so that fmt is the one and only way to format a date or time in C++. I love this paper because it adds consistency and avoids duplication. Simpler, leaner APIs!

Out pouter

P1132

out_ptr, authored by JeanHeyd Meneide is a utility to safely handle C APIs expecting T** as parameters and will be useful to anyone who ever had to deal with C APIs. I believe this was the very last paper seen by LEWG this meeting.

Another useful pointer type to deal with C apis, retain_ptr - proposed by Isabella Muerte did not make the cut for C++20 but should be adopted in C++23

A auto-joining interruptible thread.

P0660

std::jthread is a thread that can be requested to stop and that will automatically join on destruction. Very useful indeed.

Deprecating volatile

P1152

Thanks to JF Bastien, we are taking some steps towards getting rid of the volatile keyword. P1382 which will not be in C++20 will offer a sane replacement for the useful use cases of volatiles.

span’s size type

We made span’s size type consistent with size_t and offered a non-member ssize() function that returns a signed size for people who care about that kind of thing. Now, we can stop talking about it.

An overworked seal of approval

🕴️ Unicode 🕴️

ctre

We saw for the first time a proposal based on CTRE, presented by its author, Hana Dusíková. I think we are all excited by the prospect of having something like CTRE in the standard. However, we had to explain to Hana that std::regex is broken beyond repair, we will never be able to add Unicode support to it. And, given the burden of adding regex engines to the standard, we would very much please make ctre a Unicode-compliant replacement to std::regex.

But the thing is, Regex is the final boss of Unicode and the Unicode Regex TRis so massive virtually no one implements it fully. And SG-16 may not be ready to tackle that beast for a while.

Yet, we really want CTRE to be forward compatible with Unicode and UTS#18. A hurdle with that is that ctre is based on prce’s syntax which is not standardized. Fortunately, ECMAScript 2018
specifies level 1 support for Unicode so C++ can hopefully rely on that work which would simplify the wording - std::regex is derived from an older version of the ECMAScript specification.

In short, Hana will have her hands full, but Unicode support can be added incrementally as long as we plan ahead. If we manage to pull that off, it will be glorious.

Transcoding

We also discussed a proposal to describe the requirements for a transcoding API and we expect to get more paper in this area in subsequent meetings.

A bright future

As committee members, we get to live at head and beyond. Which is sometimes a curse as most of us are stuck in C++17 or older and will be for a while. C++20 conformance will take quite a while to achieve. Yet, as the end of the C++20 cycle nears, here are some proposals to look forward in C++23 and 26

I think the LEWGI and EWGI groups are an incredible success which seems to have increased the committee bandwith significantly. Bryce and JF do an incredible job out of it. Study groups are also very active, and I keep being impressed by the expertise of SG-16 (text study group) members.

See you in Cologne

I’ve very grateful to the people that gave me little choice but to be in Kona, especially Bryce and the C++ foundation. Hawaii is a great place and it is quite easy imagining staying there forever. Summer 12 months a year and a lot of varied, breathtaking landscapes, what is not to love?

However, time to get back to work (I do have a day job) and make progress on my papers. I have a todo list claiming I need to write 6R0 papers for the next meeting along the 6 I need to provide wording for. And I still have no idea why I’m doing all of that.

WG21 will meet again. The next locations are Cologne, Belfast, Prague, Bulgaria, New York 🗽 (tentatively) and Kona again in 2 years exactly. The prospect of a New York meeting is quite exciting indeed!

Most importantly, it was great seeing all the amazing committee members, even (especially ?) those we disagree with. Take care and see you next time !

See you in cologne

Share on