ISO C++ Committee – Jacksonville 2018 trip report

This trip report is provided by Timur Doumler, who joined the CLion team in fall 2017. You might know him from his work on the JUCE framework, the Audio Developer Conference (ADC) organization, and dozens of talks about modern C++ at various conferences. Now working at JetBrains, Timur continues to be active on the C++ Committee. He is now mostly involved in the Evolution Working Group (EWG), the subgroup of the committee that reviews and approves the design of new core language features. This fits well into our strategy at JetBrains: we would like to be actively involved in the committee and feed our experience with implementing language features in our C++ tools back into the ongoing work on the evolution of the C++ language.

Timur:

From the 12th to the 17th of March 2018, I traveled to Jacksonville, Florida, to attend the ISO C++ Committee meeting as JetBrains’ representative on the committee. As always, it was a great week, packed with interesting discussions and decisions towards the upcoming C++20 standard. The committee is organized into several Working Groups with many sessions taking place in parallel, making it virtually impossible to keep track of everything. So I decided to focus on EWG and cover the most relevant discussions concerning language evolution.

Day 1: Structured bindings and concepts

On Monday, EWG looked at structured bindings. This feature was one of the last-minute additions to C++17, and now that people have started using it, new issues and ideas have come up. One particular issue that we discovered here at JetBrains while implementing structured bindings for CLion 2018.1 is the inconsistency between access rules in structured binding declarations and other kinds of declarations. C++17 currently defines that for structured bindings to bind to a class, all members have to be public. This surprisingly means that the following code is ill-formed:

but if you write out the offending line without structured bindings like this, the code compiles:

We suggested a fix to remove the “public member” requirement from [dcl.struct.bind], and instead to apply the usual rules like in all other parts of the language, i.e. that the members are accessible from the context of the declaration. Coincidentally, this also makes our implementation in CLion much cleaner. The fix was approved and voted into C++20, and was further accepted as a defect report against C++17.

In EWG we then discussed various other papers proposing extensions to structured bindings, such as using them in conditions (like if (auto [x, y] = result)) and in generic lambda parameter declarations. However, we felt that none of those designs fit well enough into the language to be adopted.

The Monday evening session was spent on discussing various proposals for a “shorthand” or “terse” syntax for concepts. The most promising proposal currently is Herb Sutter’s P0745, proposing a new syntax with curly braces like Iterable{T}. But like all the other proposals, this one also had its issues, and more work is needed before the committee will have a consensus on any particular terse concept syntax.

Day 2: Let’s break some code!

Tuesday brought an unexpected turn of events. We were discussing inconsistencies between C++20’s new spaceship operator <=> and the old comparison operators <, >, <=, >=, ==, != when comparing certain built-in types. The resolution that gained consensus in EWG was to actually make changes to the old operators:

  • Change <, <=, >, >=, ==, != such that they now give the correct mathematical meaning on arithmetic types, such that, for example, static_assert(-1 > 1u);, which would pass in C++17, will break in C++20.
  • Deprecate two-way comparisons and arithmetic conversions between enumeration types and floating-point types.
  • Deprecate two-way comparisons and arithmetic conversions between two distinct enumeration types.
  • Deprecate two-way comparisons where both operators are of array type.
  • Deprecate relational comparisons between function pointers.

This is an interesting outcome. On the one hand, this finally rids C++ of some old warts and annoying oddities that have been in the language for a long time. On the other hand, it breaks compatibility with C and C++98/11/14/17. Those changes have not yet been officially voted into C++20, and I expect some controversy around them.

Day 3: Coroutines and Modules

The rest of Tuesday as well as Wednesday we discussed the state of the Coroutines TS and Modules TS. For both TSes, there are quite a few papers pointing out various unresolved issues, and even counter-proposals with significant design changes. In their current state, there is no consensus yet in the committee to merge either of them into the C++20 working paper, and more work is needed. For coroutines, the expectation is that the issues can be resolved this year and we will get coroutines in C++20. For modules, the situation is much less clear, and a lot more work is still required to get them right. Right now it seems more likely that we will have to wait until C++23 for modules in the standard. A particularly controversial aspect is the open question of what is the most efficient way to deal with #include headers if they are mixed with modules.

Here at JetBrains, our main concern with modules is to make sure that – regardless of the exact syntax and semantics that will eventually make it into the standard – this feature will be toolable. Compiler vendors are developing intermediate representation formats for modularized C++ code, and the Modules TS does not specify whether (or how) the original C++ code will be accessible through those formats – for example, for features like code inspection and refactoring. It also seems unlikely at this point that compiler vendors will align their different formats. We are working with other committee members to make sure that we will end up with a compiler ecosystem for modularized code that will work well with IDEs and other C++ tools and can provide a great experience for C++ developers.

Day 4: Compile-time programming

On Thursday, two decisions stood out as exciting for the evolution of the language. The first was EWG’s approval of P0732: in C++20, we will be able to use class types as non-type template parameters. This will finally allow us to have useful compile-time strings, along the lines of

and many other use cases. Here’s the reason why this is so tricky: during template instantiation, the compiler needs to be able to efficiently decide whether two types are the same, by comparing the mangled typename (which includes the values of non-type template parameters). P0732 offers a solution to this problem: it mandates that class types that are used as non-type template parameters must have a defaulted (compiler-generated) operator <=> guaranteeing strong equality.

The second milestone was EWG’s approval of P0784, allowing constexpr destructors and the use of new and delete in compile-time constexpr contexts. This opens the door to making vector and other standard containers constexpr, allowing them to be used for compile time metaprogramming.

Day 5: New Tooling Study Group

Friday was again an exciting day for JetBrains: the inaugural meeting of SG15, the new Tooling Study Group, took place. SG15 is a new platform in the C++ committee where vendors of IDEs and other tools can discuss challenges and future directions in C++ tooling, exchange ideas, and use their experience to inform the ongoing standardization work. This first meeting did not bring concrete results yet, but we had a great discussion about better aligning C++ build systems, package distribution, and dependency management, as well as using static analysis and refactoring to help users modernize their code.

Day 6: Plenary

Saturday was, as always, dedicated to the closing plenary session, where new wording is officially voted into the working draft for the next C++ standard. Here is a selection of features that successfully made the cut this time:

  • relaxed rules on typename, removing the need to type it if it’s unambiguous in the given context
  • allowing pack expansions in lambda init-captures
  • [[likely]] and [[unlikely]] attributes to help optimization
  • a new <version> header to replace the vacuous <ciso646>
  • extending <chrono> to calendars and time zones
  • mandating that std::string::reserve never shrinks (which also makes std::string more consistent with std::vector)
  • adding the very useful std::span – a bounds-safe view for sequences of objects

We also sent the Parallelism TS to ISO balloting, and decided to create a new Reflection TS working draft.

Overall, it was a very productive and eventful week. I believe that we are making really good progress towards C++20, and I am looking forward to the next committee meeting this June in Rapperswil, Switzerland.

JetBrains
The Drive to Develop

This entry was posted in Conference & Events and tagged , , , . Bookmark the permalink.

16 Responses to ISO C++ Committee – Jacksonville 2018 trip report

  1. Denis says:

    Hi!

    Can you please clarify something for me: as far as I understand the proposal, allowing new/delete in constexpr – you are not allowed to keep the allocated memory around, once you are done.

    Does it mean that I won’t be able to build at compile time a map and compile it into my program? (Or the built JSON from Constexpr All The Things)

    Thanks

    • Timur Doumler says:

      Hi Denis!
      No, that’s not what it means. If you allocated objects at compile time, and you didn’t deallocate them, they will be promoted to static storage duration, from which they will be accessible at runtime. It’s explained in the paper.
      Cheers,
      Timur

  2. HGH says:

    I really wonder why structured bindings don’t allow assigning to existing variables or to skip unnecessary assignments.

    • doumler says:

      Hi HGH, unfortunately I don’t quite understand what you mean, can you please elaborate? What code would you like to compile that currently doesn’t?

      • HGH says:

        Something like this:
        auto p = pair(1,2,3);
        int a = 0;
        auto [a, b, _] = p;

        1. Reassigns ‘a’
        2. Assigns a new variable ‘b’
        3. Doesn’t need the third value.

        • HGH says:

          Some of the code was swallowed but I hope it’s clear what I mean;

          • Timur Doumler says:

            Afaik,there is a paper on the table that is proposing something very similar to this. I believe we will be discussing it at the next meeting in Rapperswil.

            Often, if C++ “doesn’t allow something”, it’s not because the committee doesn’t think it would be a great idea. It’s because no one from the community has actually invested the time and effort to sit down, write a proposal paper, submit it, and present it at a committee meeting.

  3. JackHeigen says:

    Well, looks like it’s pretty clear from this we won’t be getting meta classes until c++23 at the earliest… By the time C++ fixes the compile time programming, meta programming, and ABI issuse it has, Rust will have fixed all of its major issues that I have and I’ll have fully moved to a C and Rust environment instead of C++. To no fault of JetBrains, but I can see now why Bjarne Stroustrup regrets the creation of the standards committee. It’s way too slow and spends way too much time deliberating on pedantic junk, and ends up moving unimportant libraries into the standard to act like it did something. Instead of fixing major language issues they want to add a 2D graphics library to std and add more tentacles on to the octopus. Luckily if Clion maintains rust support I’ll probably still be using Clion by that point.

    • Timur Doumler says:

      Hi JackHeigen, and thanks for your feedback!

      I can understand your frustration. But I’d like to understand it better – which major language issues would you like the committee to focus on?

      Also, to respond do your “pedantic crap” comment. I like to believe that all of the features added in C++11/14/17 are in fact useful for a significant amount of C++ developers, even if they are not useful for you. One of the strengths of C++ is that it covers a very diverse range of use cases and platforms – from desktop to mobile to embedded, from consumer apps to systems programming to critical real-time applications. Different people will find different parts of C++ useful, and the committee needs to serve all of them.

  4. Charis Marangos says:

    This is a huge bummer. Modules is by far my favourite upcoming feature and it’s something C++ desperately needs.

    • Alex says:

      totally agree, modules are a must

      • Dien Ben Phu says:

        2023 is rather far in computer future, and no modules yet (ouch)…
        C++ seems to be sinking deeper into its own complexity swamp.. not by any fault of Mr. Stroustrup of course, since he was aiming at something entirely different. General programming language requirements have meanwhile changed, and it’s not in the favour of C++ at all.
        We’re not even speaking about reflection, binary compatibility between various compilers (even of the same brand but simply different versions! argh), insane compile times, parser complexity, no garbage collector, typing everything twice (in headers and cpp files), newbie learning curve, shaky and inherently broken meta-programming, absence of continuation, no real type-safety, incompatible legacy code, etc.
        Just try to explain to a manager while you still think C++ is a good weapon of choice for your project, while the javascript-kid next door already has a prototype whipped-up and running, reachable in the manager’s browser with zero install and no compilation, which gets faster every time chrome updates, and that without moving a muscle on the kid’s side! They’re making it really hard on us to keep a straight face, these committee people 😉

        By 2023, more modern languages will probably have surpassed C++ in every way thinkable: ease-of-use, programming speed (runtime speed gets to be less of a factor: what good is a bloody fast algorithm you cannot get shipped in time, after all? And also… if you want _real_ optimal runtime speed, C, Assembly & GPU or FPGA coding are still the winning choices, and actually less complex than the conceptual labyrinth C++ is becoming (/already-is))

        ‘System Languages’ like Rust, good old C, D.. just to name a few, are already almost as powerful as C++ (and surpass it in elegance by far).

        If you are a fan of instant gray hair, just have a look at the modern javascript optimizers that go on high code level at runtime and already seriousely surpass C++ speed in some instances. (the Closure ‘compiler’ and a few others on their way). They won’t just sit and do nothing meanwhile, so I expect quite some heat from that corner, just enlarging the gap C++ still has to bridge.

        C#, javascript, Rust have a big opportunity to leave our beloved C++ in the dust with no chance of ever catching up again… my heart just sank some 2 meters deeper when reading the news about breaking backward compatibility (if that’s consensus, I fear it’s a precedent for more of the same), which means more conditional compilation, more headaches, less support for decisions to do entire projects in C++.
        Decent C++ coders become scarcer by the minute, and more expensive (good in the short term, but catastrophic in the long run.. how many active Cobol coders do you know that walk without a geriatric rack?)

        By the time the committee is done with its bureaucratic work, there will be one large incomprehensible mess, compilers full of contradictory implementations, a language way too complicated to grasp for newcomers and veterans alike, and young coders might as well shift their focus entirely away from C++, as they are doing already. It’s Gott’s law, nothing more, nothing less, the decline has started and is gaining momentum rapidly.
        I better grab some modern programming language books and start reading, because at this pace, there will be no more C++ hegemony in 5 to 10 years from now, simple because the world moved on. Don’t know if that’s such a bad thing, actually, if you like a fresh wind now and then.

        So…still struggling with modules.. really? we’re 2018 for Turing’s sake!! everyone has modules, even Python has (for those script kids who consider that a programming language 😉

        Another sad day in C++ land, that’s what I take away from it. damnit!
        Is this history catching up with the VHS tape all over again?
        It’s seriousely starting to look like that from where I’m standing, doing C++ for the last 20 years or so.

  5. HGH says:

    I think this type of code is very fragile:
    class Foo {
    int b;
    int a;
    void bar(const Foo& other) {
    auto [b1, a1] = other; // Error: ‘a’ and ‘b’ are private!
    // …
    }
    };

    Then somebody decides to order the variables alphabetically:
    class Foo {
    int a;
    int b;
    void bar(const Foo& other) {
    auto [b1, a1] = other; // Error: ‘a’ and ‘b’ are private!
    // …
    }
    };
    What happens then?
    Reordering the elements of a tuple isn’t psychologically as easy as the members of a class. Without some sort of “hard-binding” this will be a source of unintentional bugs.

  6. Martin says:

    Does P0732 mean you could also finally pass a lambda to a template since it’s just a function object under the hood?
    Partly related, how does it interact with template auto parameters?

    • Timur Doumler says:

      P0732 lets you use an object of class type as a non-type template parameter if that class type has a default-generated (non-user-provided) operator<=>. In the case of a template auto parameter, my understanding is that it would work as expected, i.e. if the type deduced for the provided argument satisfies that condition. Lambdas however do not satisfy that condition.

Leave a Reply

Your email address will not be published. Required fields are marked *