Trip Report: March 2010 ISO C++ Standards Meeting

[Note: I usually post trip reports after the public post-meeting mailing goes live a few weeks after the meeting, so that I can provide links to minutes and papers. This time, I wanted to post the report right away to share the news. If you’re interested in the post-meeting papers, including the official minutes, watch the 2010 papers page which is where they will appear in a few weeks.]

 

The ISO C++ committee met in Pittsburgh, PA, USA on March 8-13, 2010, hosted by the CERT Software Engineering Institute at Carnegie Mellon University. As usual, about 50 experts attended, and we had eight official national body delegations from Canada, Finland, France, Netherlands, Spain, Switzerland, United Kingdom, and United States.

IMG_0396The meeting just concluded a few minutes ago (yes, the meetings run through Saturday afternoon). Here are some highlights of what happened today, which was another landmark in the progression of the C++0x standard.

Approved Final Committee Draft (FCD) for C++0x

The biggest news is that this afternoon we voted in the final remaining feature changes to C++0x, and to much applause then unanimously approved the text for international ballot as a Final Committee Draft (FCD). FCD means that, assuming no surprises, we intend to do only bug fixes and editorial corrections for the next year or so, and then ballot a final standard. If we can do that, assuming all goes well, C++0x could officially be published as soon as next year as ISO C++ 2011, and we can stop with the “x-is-hex” jokes and just start calling it C++11.

This is a big milestone, and it was achieved thanks to removing a couple of controversial features last summer and a whole lot of work by the ISO C++ committee members over the past six months in particular. That work includes countless hours spent between our full face-to-face meetings at face-to-face ad-hoc meetings to swat library bugs, teleconferences on resolving core language questions, and triple-digit person-hours invested in four teleconferences during December-February purely about C and C++ compatibility that have greatly helped to identify and attempt to resolve minor areas of divergence between the C++0x draft standard and the C1x draft standard (as both are now in progress; C1x is targeting completion and publication in 2012).

All in all, your committee members have put in an enormous amount of effort to bring this in, and the draft is in far better shape for this meeting than anyone could have expected last summer. For comparison, in my and several others’ opinions, it’s in better shape than the FCD of the C++98 standard.

Since we’re closing down this round of standardization, we didn’t make many exciting technical changes. Here are two technical highlights of the meeting that are likely of general interest, finally adopting changes we’ve contemplated before.

Removed Export Template

As I reported after the last meeting (here and here), the committee considered the question of whether to deprecate, remove, or leave in the “export template” feature.

For context, the only reason we’re even considering this is because Edison Design Group (EDG), the only company to ever implement export, is recommending export be removed or deprecated. Recall that back in the 1990s the committee originally voted the feature in over EDG’s objections in the first place, then in the late 1990s and early 2000s EDG graciously and gallantly went on to invest enormous effort to implement the feature in order to conform to the standard, and so the committee was loath to punish them again by now removing the feature on them. However, given the passage of time, EDG reports that their experience in the field has been that nearly no one actually uses the feature, and that it would be right (and okay with EDG) to deprecate or remove it.

At our previous meeting, the general sentiment was in favor of deprecation only. However, at this meeting EDG reported that they would prefer the feature to be removed rather than just deprecated, because a deprecated feature is still part of the standard and required for conformance. By removing it from C++0x, it removes the maintenance burden of being forced to support export indefinitely to maintain full standards conformance (though of course EDG will continue to support it as an extension in their compiler front end for however long seems right based on their own customers’ demand).

The committee agreed, and today voted to remove export entirely from C++0x. The “export” keyword is still reserved for future use, but has no defined meaning in the C++0x standard.

Deprecated Exception Specifications, Added noexcept

As also considered at our previous meeting, this week we went ahead and deprecated throw-specifications (e.g., throw(), throw( Base, Derived1 )). For rationale, see the two background references referred to in the proposal, one of which is an article by me:

As noted in the second reference, “A non-inline function is the one place a ‘throws nothing’ [i.e., throw()] exception-specification may have some benefit with some compilers.” Because this would have some utility, there is a replacement for empty exception-specifications… the noexcept keyword, which has the basic use syntax “void f() noexcept {…}”. It optionally takes a compile-time constant true/false expression that if true means the noexcept is in force, which helps libraries to write efficient overloads. This feature will be written about for years to come, but that’s the basic idea.

Here’s the concise summary from the core working group report by Steve Adamczyk (of EDG fame and longtime core working group chair):

We discussed two things related to exception specifications: noexcept (N3050), and deprecating exception specifications (N3051). There was some spirited discussion of what happens when you violate a promise not to throw. In the end, we decided that in such a circumstance terminate() gets called, and it’s unspecified whether any cleanup is done for local variables between the throw point and the point of the violated noexcept. It’s believed that for efficient implementations of exception handling a noexcept will not add any overhead and will not restrict optimization opportunities.

The old-style exception specifications, including the throw() form, will now be deprecated. The library specification needs to be updated to use noexcept instead, and that won’t happen at this meeting.

Note that the decision to call terminate() is not final and alternatives will be considered at future meetings. There was general (but not universal) agreement that the program should not be allowed to continue executing if a noexcept is violated because in that case the program will almost certainly be in a corrupt state, and so the consensus was in favor of guaranteeing to call terminate() instead of allowing arbitrary undefined behavior, but it’s possible that a comfortable middle ground between those two options may yet be found.

Looking Forward

We wrapped up with a presentation of the scheduled dates and locations for the next few ISO C++ standards committee meetings (meeting information link included where available):

Finally, here’s a copy of summary slide I presented, which will also be in the post-meeting mailing. Here’s to C++11 (we hope)!

 

Pittsburgh slide.jpg

42 thoughts on “Trip Report: March 2010 ISO C++ Standards Meeting

  1. MFC has been a terrible GUI lib for a very long time. Try using a more modern C++ GUI lib and you’ll make your life a lot more pleasant. Personally, I’m a fan of Qt.

  2. Hi to u all, im a beginner in C++, im lovin it a lot, hmm i was thinking what can be done about windows programming , regarding to MFC, cos .NET framework is much better, than on the other hand managed C++ is something i dont like at all….

    Thnx 4 the answer..

  3. How I understand the basic problem consists in what will occur if function declared with throw() will generate exception. However the call unexpected() isn’t natural and speaks about badly designed program, but has the right to existence in the debugging version. And that problem can be partially solved by the static analysis of hierarchy of functions with their specifications of exceptions and types of exceptions generated in their bodies at stage of compilation with corresponding optimisations and generating of corresponding warnings. And for this purpose it is not necessary to enter new “especial” keyword into language core.

    Waiting for corresponding articles.

  4. Hi Herb, great news!
    What about the feature that we discussed while you were in Tokyo, about making noexcept as strong as const (e.g. only noexcept code can be called from noexcept etc?)
    In this case it will be much easier and safe to write exception-safe code:
    void f()
    {
    // code that may throw
    vec.insert(3); // may throw

    // done with trowing code, now calling only no-throw stuff
    noexcept
    {
    vec.size(); // ok, vector::size is noexcept
    vec.insert(5); // will not compile, as vector::insert may throw
    }
    }

  5. @Steve: Correct, except only VC++’s implementation incurs that overhead only in 32-bit mode. The 64-bit mode is already fast.

    @Brendan: No, I’m glad to say this feature is not about VC++. Noexcept will improve optimization opportunities on all compilers. I plan to write about this in the near future, stay tuned.

  6. Wait, so this is just a feature to workaround a bad implementation of exceptions in VC++?

    I’m not saying such a thing shouldn’t exist, after all people need to write cross platform code sometimes. However, it’s kind of misleading to present it as making non-throwing functions more efficient, when to my knowledge they are already free on GCC…

    Concretely this is only an optimisation for compilers that *dynamically* construct their unwind information, instead of doing it statically.

  7. > But why add another keyword of “noexcept” instead of using
    >“[[noexcept]]” (or some similar attribute)?
    The committee has taken the view that attributes should not affect the meaning of the program. Attributes are intended for compiler-specific features that can be ignored by other compilers, or something like optimization hints. Because noexcept affects the meaning of the program, it should not be an attribute.

  8. > Exceptions have zero run time overhead if they are not thrown.
    Not true for all implementations, notably VC++.
    Even with no apparent runtime overhead, exceptions can still have an effect on generated code that is executed.

    > If noexcept is being added only for optimisation opportunities then
    > there is no point whatsoever.
    With some compilers, functions that need exception-handling code cannot be inlined. The “throw()” clause means that in effect, the function must be enclosed in a function try-block, with something to catch any exception that escapes. All this means possibly less-efficient code and loss of inlining.

    One motivation for the “throw()” clause on a function F is helping the compiler to optimize functions that call F. If a function G makes no calls that could result in an exception, additional optimizations might be available. In particular, if G is declared with “throw()”, the extra code to catch an errant exception can be omitted, allowing G to be inlined.

    The “noexcept” keyword means that a compiler could probably omit all inefficiencies, and allow inlining of the function; terminate could be called by existing mechanisms. The result would be absolutely zero cost for the declaration, in addition to the existing gains from knowing the function cannot exit via an exception.

    >I *am* struggling to understand how the somewhat awkward,
    > double-negative nothrow(false) could be of any use.
    Almost always you will use “noexcept”. The “noexcept(b)” form, where b is a boolean expression, allows noexcept to be conditionally specified via a constant-expression or template argument.
    noexcept(true) is exactly equivalent to noexcept.
    noexcept(false) is exactly equivalent to omitting noexcept.
    I would not expect any programmer to write “noexcept(true)” or noexcept(false)”.

  9. But why add another keyword of “noexcept” instead of using “[[noexcept]]” (or some similar attribute)? New keywords always make me nervous due to existing code, and exception hints would look like a natural issue of function attributes to me.

  10. Brendan,

    I like your ideas. Please create proposals for them. That’s how they’ll get included in the next Standard or TR.

  11. I don’t think there’s anything in this spec that would interfere with adding a static requirement to future version of the standard, or with vendors that would like to optionally check it statically.

    The problem they’re trying to solve is that throw() is currently optimized in some compilers, and prevents optimization in others. A programmer should be able to rest assured that nothrow will never make their performance *worse*.

    The problem with making nothrow statically checked *today* is that there’s huge amounts of code that doesn’t include nothrow, so if a nothrow function can only call other nothrow functions, then you’re going to have to add a lot of try/catch blocks in code that you *know* isn’t going to throw an exception, and that’s the *opposite* of an optimization. The only alternative I can think of is adding some sort of nothrow_cast.

    I can also understand why the WG would want to be conservative this late in the standardization process, after what happened with ‘export’ during C++98. I don’t think this would be as difficult to implement as export, but it may have some unforeseen side-effects, especially if there’s no known implementation.

    Now, I *am* struggling to understand how the somewhat awkward, double-negative nothrow(false) could be of any use.

  12. There is a nothrow version of new…

    Non-throwing code is a special case in C++, most functions can throw and you usually should just write exception safe code with std::shared_ptr or whatever.

    Most C++ users never even knew about the existence of old style exception specifications, and Visual Studios never implemented them…

    If we had no noexcept, I don’t think it would be a tragedy… however, I do think it’s kind of pointless to do it at all unless it is static.

    If it were static I suspect it would mostly be used to provide callbacks for C libraries, and other cases where a callback can’t throw. If it is dynamic I suspect it won’t be used, and probably not widely implemented, as that’s what happened with throw().

  13. Daveed is a top-notch expert and author and a respected colleague. He works for EDG, knows the export template feature better than all but a handful of people in the world, and is very passionate about it. He doesn’t speak for EDG, however. The text of this blog post about export and EDG was reviewed and approved in advance by Steve Adamczyk (president of EDG, and core working group chair).

  14. This reminds me of the introduction of const. Way back when, in the days of K&R C, there was no such thing as const. When it was introduced, there was a whole lot of C code that didn’t use const, and this greatly slowed its adoption. Nevertheless, it’s in wide use today, and I certainly hope all of us reading this write const-correct code.

    Similarly, library writers can start writing noexcept in their libraries, and application developers can start writing noexcept, and retrofitting it slowly on existing code, and using it on their new code. It could take a decade or two to be in mostly universal use, but C++ will presumably be used then.

    The only problem I’ve got with it is that it a whole lot of the library can’t be noexcept. If I resize or push_back on a vector, it might throw bad_alloc. The container and algorithm libraries were designed to be used with exceptions, to be exception-safe to the maximum degree possible, and they use exception.

  15. Can you elaborate on EDG position on “export template”.

    From following a few threads on comp.std.c++ and comp.lang.c++.moderated, I had the impression that they actually were in favor of export, and felt that their position has been misrepresented. Daveed Vandervoode in particular came out several times specifically in defense of export, basing it on his experience of implementing it in EDG, and consequently using it. When did that position change?

  16. Exceptions have zero run time overhead if they are not thrown. Not a single extra instruction in the code path. Exception handling tables are built *statically* at compile time.

    See this: http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c#307716

    If noexcept is being added only for optimisation opportunities then there is no point whatsoever.

    On GCC at least, exceptions *do* bulk up the code a little by adding exception handling tables, but I don’t think making a function noexcept will remove the need for those tables entirely anyway, since exceptions can still happen *within* the function, just not be thrown outside of it. So as far as I can tell, the stuff about noexcept or throw() being an optimisation is just not true. I guess GCC developers would be better to ask though…

    As for the uses of a static noexcept, plenty of C code doesn’t throw exceptions… In C headers, usually there is an extern “C” controlled by a macro. You could add a noexcept to that macro as well.

  17. I think the main problem with a static noexcept (or any other type system extension) is the large existing body of C and C++ code written without it, and the need for new code to use the old code easily.

    If you wanted to write a new static-noexcept function that called old code, and were confident that none of the called functions threw exceptions (but they weren’t declared noexcept), you’d have to basically put a try/catch(…) block around all the whole new function. That’s a bit verbose, and might nullify the effect of the noexcept optimization in the first place. It also wouldn’t work in constructors or destructors where a new class derived from, or had a member of, an old class type, because you can’t suppress exceptions thrown during member initialization to satisfy the static noexcept checker.

    It wouldn’t surprise me if some compiler vendors offered warnings for statically detected noexcept violations, though.

  18. I agree, I don’t see any real gain in `noexcept` over `throw()` if both are required to call `terminate()` upon exception.

    Unless `noexcept` is required to be checked at compile time this is not an optimization.

    Unfortunately I cannot find N3050 on the official JTC1/SC22/WG21 2010 mailings page at this time.

    The thing `noexcept` has that `throw()` doesn’t is the optional boolean to enable it: `noexcept(true)` and `noexcept(false)`. But, I feel that `throw()` could be augmented with this functionality: `throw(true)` and `throw(false)`.

    Replace:
    exception-specification:
    throw ( type-id-list opt )

    with:
    exception-specification:
    throw ( boolean-literal opt ) // perhaps not boolean-literal, perhaps convertible-to-boolean?
    throw ( type-id-list ) // deprecated

    Personally I don’t like the negative form of `noexcept`, for instance `noexcept(false)`. I would rather like to use a positive form: `maythrow(true)`, but that on the other hand would require to write `maythrow(false)` instead of just `noexcept`.

  19. For me, C++0x is already a huge improvement… and I think that some small targeted improvements on a quicker schedule would have a lot of impact. The biggest problem with C++0x is that there is 14 years between publication of standards.

    Small fixes that would help a lot:

    1. a standard programmatic interface for generating stack traces… This is something everyone has to roll themselves right now, and is important for logging. They should be attached to std::exception by default.

    2. Some kind of parser change to avoid the MVP, or at least reduce its occurrences.

    3. std::to_str, std::format, ans std::print functions. Here’s a really basic implementation: http://catphive.net/blog/?p=262

    4. Tools to make it simpler to maintain a library with a stable ABI. Currently this is a trickier than it could be in C++.

  20. I’m kind of iffy on what the point of noexcept is, if it still has the underlying problem that throw() did, i.e. it doesn’t cause the compiler to statically prevent exceptions being thrown. After all, that’s what most people want from exceptions specifications…

    Why don’t you just mangle noexcept into the *type* of the function in the same way that *const* is in the type of the function?

    Then noexcept functions can only call other noexcept functions, and any non-noexcept code that is called, must be surrounded by a catch(…). This would actually be *useful*.

    Having noexcept that calls terminate is not an improvement over the existing throw() syntax. I find this argument that there would be some kind of compiler optimisation that takes advantage of it kind of vague. At least with how GCC does exceptions(http://www.codesourcery.com/public/cxx-abi/abi-eh.html) I don’t think this is possible. Maybe I am wrong.

  21. I just want to add my thanks for your efforts and those of the other committee members. I’m glad you’re in the vanguard doing this work so I don’t have to!

  22. With any declaration of behavior, there’s two ways to go. First, the implementation can enforce it, perhaps at some cost. The compiler can insert checks to call terminate() if an exception is thrown. Second, the compiler can take it as optimization advice that the programmer is responsible for getting right, and compile the function with no regard for exceptions. (Or it can go either way, depending on compile options. Common Lisp type declarations are often treated this way.)

  23. It may be called C++11, but in my heart it will always be C++0xB.

    Seriously, though, congrats. So what’s the plan after C++11 is officially standardized? I guess concepts, decimal types, modules, and tr2 will all be released as individual TRs? When writing about the removal of concepts from C++0x, Stroustrup seemed worried that the WG will lose some momentum when the standard is completed.

  24. You mentioned that there was not universal agreement between calling terminate() vs allowing undefined behavior if a noexcept promise was violated. Could you expand on what were the reasons for even considering undefined behavior to continue? Given noexcept is new, there isn’t a problem of backward compatibility. So why then was undefined behavior being considered as an option?

  25. With exception specifications getting deprecated, is there a plan to remove exception specifications from standard library functions that currently have them (or replace them with noexcept where appropriate)?

    For example, the member functions of std::exception.

    (This is probably discussed in N3050 or N3051, but they have yet to be published)

  26. Concepts would be the most important change to C++ since it was codified, and would bring the famous difficulty of the language towards novices down to a reasonable level.

    They need to be re-added.

Comments are closed.