Red Hat at the ISO C++ Standards Meeting (June 2014): Core and Library

In June, Red Hat engineers Jason Merrill, Torvald Riegel and Jonathan Wakely attended the ISO C++ standards committee meeting, held in Rapperswil, Switzerland. This post contains reports on the core language work by Jason, and the library work by Jonathan.  Torvald’s report out on Parallelism and Concurrency is here.

The next C++ meeting will be November 3-8 at the University of Illinois in Urbana-Champaign.

Core (Jason)

Because the C++14 standard ballot is still open we weren’t supposed to make any changes to the working draft at this meeting.  But since we’ve started producing intermediate Technical Specification (TS) documents as well as the main standard, we could make changes to those.  So there was a significant focus on TS work at this meeting in addition to the usual issue processing.

As usual, I spent most of the week in the Core language working group (CWG). Core spent most of the week (Monday, Tuesday and most of Wednesday) reviewing the proposed concepts (formerly “lite”) TS (N4040).  The largest change we wanted to make to the design was allowing constraints on non-template declarations, not just templates; this was mostly for the purpose of improving consistency, but I can imagine it could be used for function versioning based on sizeof and the like.  And then there were lots of smaller changes needed to clarify exactly how things work.  The upshot was that there was no way that Andrew Sutton could update the paper and get it back to us for another round of review this week, so the plan is to do more review in a teleconference next month with the goal of approving the TS at the Urbana meeting.

It now seems that this proposal is definitely going to become a TS and then likely the big new feature in 2017, so I think it would be good for me to work on getting it into the GCC trunk sooner rather than later.

The other potential TS we reviewed was the Transactional Memory paper (N3999). CWG was very concerned about the idea that we would emit two copies of every function not explicitly marked as transaction-unsafe or transaction-safe, and suggested that instead of that, we should require any function that is called from transaction-safe context and is not defined in the current translation unit to be declared transaction-safe.  Torvald says that this shouldn’t affect the GCC implementation significantly.  This TS is also expected to be approved in Urbana.

First thing on Wednesday morning Core took a break from concepts to do issue triage while many of us, including myself, went to a presentation of Gabriel dos Reis’ modules proposal (N4047).  The other folks in the room that have been experimenting with modules, Doug Gregor and Daveed Vandevoorde, noted that most of the proposal was very similar to their systems, and it was generally agreed that the three of them should get together and work out a common proposal.  One difference that was raised was the handling of macros: gdr’s proposal says that macros have no effect on modules, but Doug said that he tried that and users revolted; in the end he settled on ignoring any macros defined in source files, but cause macros defined on the command line to affect which copy of a module is loaded (and perhaps compiled on demand). Modules continue to seem like an attractive feature for improving compile times and likely for managing library exports, but after Diego Novillo and Lawrence Crowl’s problems with their PPH project for GCC, I’m concerned about how much work it will be to implement.

While I was away the rest of Core considered DR 1048 – an issue I had submitted in 2010 about inconsistency between auto and lambda return type deduction, which was resolved by my return type deduction proposal that went into C++14. But they didn’t notice that and decided not to make a change to address the inconsistency.  I raised this on the reflector, and everyone seems to agree with me – just kind of amusing that they decided to dismiss an issue I submitted during the one time during the week I was out of the room…

Some smaller minor papers we reviewed:

N4051: Allow typename in a template template parameter.  Currently, even though template type parameters can be introduced with “typename” or “class“, a template template parameter still needs to use “class“.  This proposal fixes that inconsistency.

N3981: Removing trigraphs??!  For most users, trigraphs are useless, just an occasional annoyance.  This paper proposes removing them from the language, and points out that implementations that want to continue to support them are free to do so under the implementation-defined mapping from physical source file characters to the basic source character set.

N4029: Let return be direct and explicit.  This proposal addresses the issue that since the return statement performs copy-initialization, it cannot use explicit constructors.  The original proposal suggested that return should always be direct-initialization instead, but it was adjusted to only propose that for “return { expr }“.  There was a fair amount of grumbling about this proposal, including some people from the Evolution working group who didn’t think they had voted to send the proposal on to core, but the EWG presentation on Friday included it.  My preference would be to write “return explicit“, but it sounds like that was considered and rejected.

N3994: Range-based for-loops: the next generation.  Many range-based for-loops use ‘auto‘ in the declaration, and this proposal allows people to leave it out: an identifier without an explicit type will be declared with “auto&&“.

N3928: Extending static_assert.  This just proposes to allow people to use static_assert with only the condition argument, making the string argument optional.

N4026: Nested namespace definition was endorsed by EWG, but did not have proposed wording, so it hasn’t gone to Core review yet.  This proposal just allows people to re-open nested namespaces directly with

namespace A::B::C { ... }

rather than

namespace A { namespace B { namespace C { ... } } }

One significant thing that came up in issue processing was an idea about a new model for triviality.  Triviality of deleted functions has been kind of hard to quantify for a while; back at the Pittsburgh meeting in 2010 we decided that a function doesn’t have to be callable to be trivial, primarily so that we could make a trivial function private, and extended that to deleted functions as well.  But that doesn’t quite make sense for functions that are implicitly deleted because their implicit definition would be ill-formed; does an ill-formed constructor call non-trivial subobject constructors? In Rapperswil there was broad interest in an approach that says that deleted member functions are non-trivial, but then also changes the notion of trivially copyable so that it only requires one trivial copy/move constructor, not that all of them be trivial.

We didn’t do a lot of review of issue drafting at this meeting, but my drafting for issue 1467 (which also resolves 5 others) was moved to Ready status.  It deals with list-initialization from an initializer list of one element of the same type, i.e.

A a1 { a };

Previously this was ill-formed if A is an aggregate, because it does not have itself as a data member; now it will be equivalent to

A a1 (a);

There was some skepticism about Herb Sutter’s ABI proposal, but EWG encouraged him to keep working on it.  I believe Michael Wong from IBM is going to work with him.

Another paper working its way through EWG is N3988: Towards restrict-like aliasing semantics for C++.  This proposal suggests something more elaborate than C’s restrict: allowing users to annotate declarations with an alias set tag, which can be just an identifier or even an expression, where the the value of the expression (whether constant or not) affects which alias set the declaration belongs to.

It looks like C++ VLAs are dead at this point: at the Bristol meeting they were voted out of the working paper into an Array TS, and at this meeting it sounded like there is no interest in actually producing the Array TS.  So I guess I should remove the “array of runtime bound” diagnostics from the compiler.

Library (Jonathan)

As Jason said above, we couldn’t make any changes to the C++ working draft at the meeting, but the Library (LWG) and Library Evolution (LEWG) working groups where kept very busy processing issues and working on several Technical Specifications that are currently active.

The File System public draft (PDTS) had received a number of National Body (NB) comments which needed to be resolved and in addition there were a number of issues identified by Microsoft’s implementation of the spec.  With the author of the original Boost implementation and the Microsoft one present, as well as a number of people familiar with the POSIX file-related APIs, we were able to resolve all the issues one way or another and the updated draft is now ready for publication as an ISO TS. This will be the first C++ TS and should be published shortly after the new C++14 standard, so getting that out the door was another significant milestone.

There was quite a lot of work on the Library Fundamentals TS, which we wanted to get ready for a PDTS after the meeting, and in parallel with that decide which new features to include in a second Fundamentals TS.

For the first Fundamentals TS there were some final fixes for the std::experimental::optional class template, some of them having taken a lot of to-ing and fro-ing to reach consensus.

The biggest last-minute change for the Fundamentals TS was as a result of my paper, “N4041 Concerns with changing existing types in Technical Specifications“. Following a joint discussion between LWG and LEWG it was decided that making ABI-breaking changes to existing types was not worth it in this case, because the features necessitating the changes just aren’t important enough. As a result GCC users will not be forced to choose between enabling new features and compatibility with previous GCC releases. The new approach is for the TS to define new, distinct types such as std::experimental::function instead of requiring changes to std::function. This avoids changing the ABI of std::function, but requires implementors to maintain two versions, so some people would have preferred to drop the new features entirely. At least this way we can give the new version of the types to users and find out if they are interested enough in the new features for them to become part of the next C++ standard (which is one of the aims of a TS).

With that change the Library Fundamentals draft is going to the PDTS stage.

For the second Fundamentals TS, the only feature definitely included so far is “N4022 a generalized callable negator” which would replace the std::not1 and std::not2 function template. I had helped the author improve the proposal after the last meeting and presented it on his behalf at this meeting. The feature is useful for function composition and is something we can probably implement quickly and easily for libstdc++ users.

Another proposal that was intended for inclusion in the second Fundamentals TS is “N3997 Centralized Defensive-Programming Support for Narrow Contracts“. It was controversial when presented to the full committee and the motion to include it in the TS was withdrawn. A number of committee members were concerned that it supports a single style of designing and testing libraries, and that there are other valid approaches, but putting this into an official ISO document would seem to bless this as the “approved” way to do things.

There was a lot of discussion in LEWG about how to improve support for hashing. One approach, proposed in N3980 “Types don’t know #”, is to provide a generic framework for hashing arbitrary types using arbitrary hash algorithms, so that users don’t need to decide on a single hash function for their types but instead can define how their types expose their contents to any hash function that asks for them. This allows the choice of hash function for any part of a program to vary independently to the choices of data type and the definition of those types. This had a lot of support from many people as an elegant and extensible solution, but Google in particular are opposed to making it easy for users to swap in and out different hash functions in this way, as they believe it will lead to poor quality hash functions being used in ways that are hard to fix at a later date. Google’s preference is to rely on a single hash function throughout the program (by using the std::hash template).  This means the compiler implementation can ensure it chooses a well-known, strong hash function for std::hash which has been studied and vetted by experts, and if weaknesses are found in that function then the standard library can switch to a different implementation of std::hash, requiring changes in only one place and fixing all the code that uses it. Due to this, Google are keen to make it easier to use std::hash for user-defined types, rather than making it easier to use any arbitrary hash function, and that’s what their proposal, N3983 “Hashing tuple-like types” tries to do. Both proposals were well-received by the LEWG, but it’s not clear whether we want to take two overlapping, and somewhat contradictory, approaches to hashing. Until something is done we have the worst of both worlds, in that users have no choice but to create their own poor quality hash values for their types, because we don’t offer them any way to do it better.

The LEWG also looked at the “N4029: Let return be direct and explicit” proposal that Jason mentioned. A number of people are very concerned that library authors have intentionally disabled implicit conversions using the ‘explicit‘ keyword and that changing the core language to ignore that goes against careful design decisions for the sake of convenience. I expect we’ll see more discussion on this too.

A number of other, far less controversial proposals were reviewed by the LEWG and forwarded to LWG for inclusion in the second Fundamentals TS. This is causing a bit of a backlog in LWG, with LEWG sending almost everything they look at to be polished by LWG, who are not able to keep up. One of the main purposes of using TSs is to help the committee move faster and get more useful tools into our users’ hands sooner, so the chairs are considering ways to avoid too much delay.

The Parallelism TS also underwent a lengthy review by the LWG and is also going forward to the PDTS stage. The Concurrency TS is still a work in progress and the LWG didn’t spend any time on it at this meeting.

Finally, for the TS side of things, the Networking study group have not been meeting recently and their work appears to have stalled, much to many people’s disappointment (C++ is heavily used in networking applications, from HPC systems to financial markets to desktop web browsers, but the C++ standard library offers nothing to help, leaving users to rely on the C library or third-party frameworks). In Rapperswil we decided to resurrect a 2007 proposal (N2175 “Networking Library Proposal for TR2”) and to prepare it as a Networking TS. This proposal is based on the ASIO library which has been part of Boost for many years and is widely used.  Although there is expected to be opposition from some committee members the LEWG was strongly in favour of using ASIO as the basis for a C++ networking TS.

As well as all the TS work, the LWG managed to triage all our open issue reports and resolve all the highest priority ones and a few of the others (including some where there is implementation divergence and we felt it was important to agree on the right direction so users can know what to expect in portable programs).

There was one outstanding NB comment on the C++14 draft which needed to be looked at (LWG 2118). Progress has been made but it’s a complicated and tricky area, so nothing has changed for C++14.

Share