October 2010 C++ Standards Committee Mailing
Thursday, 21 October 2010
The October 2010 mailing for the C++ Standards Committee was published earlier this week. This is the pre-meeting mailing for the November 2010 committee meeting.
As well as the usual core and library issues lists, this mailing also includes a Summary of the status of the FCD comments, along with a whole host of papers attempting to address some the remaining FCD comments.
To move or not to move
The big issue of the upcoming meeting is looking to be whether or not the compiler should implicitly generate move constructors and move assignment operators akin to the copy constructors and copy assignment operators that are currently auto generated. The wording in the FCD requires this, but people are concerned that this will break existing code when people start using their code with a C++0x compiler and library. There are two papers on the subject in the mailing: N3153: Implicit Move Must Go by Dave Abrahams, and N3174: To move or not to move by Bjarne Stroustrup.
There seems to be consensus among committee members that the FCD requires compilers to generate the move constructor and move assignment operator in cases that will break existing code. The key question is whether the breakage can be limited by restricting the cases in which the move members are implicitly generated, or whether implicit generation should be abandoned altogether. The various options are explained very clearly in the papers.
Exceptions and Destructors
N3166: Destructors default to noexcept is another potentially controversial issue. It is generally acknowledged that throwing exceptions from destructors is a bad idea, not least because this leads to termination if the destructor is invoked whilst the stack is being unwound due to another exception. Herb Sutter wrote about this way back in 1998 when the original C++ standard was hot off the presses, in GotW #47: Uncaught Exceptions.
The proposal in the paper comes from a Finnish comment on the FCD,
and is quite simple: by default all destructors are assumed to be
marked noexcept(true)
(which is the new way of saying
they cannot throw an exception, similar to an exception specification
of throw()
), unless they explicitly have a non-empty
exception specification or are marked
noexcept(false)
.
Since it is generally good practice not to throw from a destructor,
you'd think this would be uncontroversial. Unfortunately it is not the
case — there are currently situations where throwing from a
destructor has defined behaviour, and even does exactly what people
want. The example most frequently cited is the SOCI project for accessing
databases from C++. This library provides an easy syntax for
constructing SQL queries using the <<
operator. The
operator builds a temporary object which executes the SQL in the
destructor. If the SQL is invalid, or executing it causes an exception
for any other reason then the destructor throws. Changing destructors
to be noexcept(true)
by default will make such code
terminate on a database error unless the destructor is updated to
declare that it can throw exceptions. Working code with defined
behaviour is thus broken when recompiled with a C++0x compiler.
Concurrency-related papers
There are 3 concurrency-related papers in this mailing, which I've summarised below.
- N3152: Progress guarantees for C++0x (US 3 and US 186)
The FCD does not make any progress guarantees when multiple threads are used. In particular, writes made by one thread do not ever have to become visible to other threads, and threads aren't guaranteed ever to actually run at all. This paper looks at the issues and provides wording for minimal guarantees.
- N3164: Adjusting C++ Atomics for C Compatibility
This is an update to N3137 from the last mailing, which provides detailed wording updates for the required changes to regain compatibility with C1X atomics.
- N3170: Clarifying C++ Futures
There were a few FCD comments from the US about the use of futures; this paper outlines all the issues and potential solutions. The proposed changes are actually fairly minor though:
-
future
gains ashare()
member function for easy conversion to the correspondingshared_future
type; - Accessing a
shared_future
for whichvalid()
isfalse
is now required to throw an exception rather than be undefined behaviour; atomic_future
is to be removed;
A few minor changes have also been made to the wording to make things clearer.
-
If you have any opinions on any of the papers listed here, or the resolution of any NB comments, please add them to the comments for this post.
Posted by Anthony Williams
[/ cplusplus /] permanent link
Tags: C++0x, C++, standards, concurrency
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Design and Content Copyright © 2005-2024 Just Software Solutions Ltd. All rights reserved. | Privacy Policy
5 Comments
It is so easy now to get the sims freeplay cheats online from these generator that are too good.
Hi, I have a comment to C++ Standard Core Language Active Issue 1168 (Additional reasons to call std::terminate), which is a response to NB comment GB 47. It proposes the following text:
"In some situations exception handling must be abandoned for less subtle error handling techniques. [Note: These situations are: * ... the list goes ... * when the destructor or the copy assignment operator is invoked on a std::thread object that refers to a joinable thread [...]" Well we know what it means, but I think there is a loic error in this text. The header of the list says that the situations listed describe when exception handling must be abandoned. So, situation in each bullet implies that exception handling was in progress. But in case of the situation where we copy a joinable std::thread, there is no exception handling in progress.The situation can also happen if we switch off exceptions in our compiler. The last bullet just does not fit into the list. It should be removed, or even better it should be left there, but the header of the list should be changed to something like: "In some situations, program execution should be abandoned and error handling techniques less subtle than exception handling need to be employed." This makes sense as with the inclusion of this behavior of std::thread, the C++ standard opened a new feture: not only do we terminate on exception handling mechanism failure, but also upon some application design errors. There may be moreof these situations in the future once we have the precedent. (A good precedent, by the way.)
There is yet one other issue, and that's initializer lists. Bjarne's paper ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3139.pdf ) outlines the problem with this new construct. I would expect there will some discussion at the Batavia meeting about this, as it's still not clear what to do here that won't be just one more patch rule to the other lookup rules.
As far as I can tell, there is no way to use initializer lists to do move construction.
I would like to be able to say something like
typedef std::unique_ptr<int> ptr
int *p, *q, *r; std::vector<ptr> vec{{p},{q},{r}}; or int *p, *q, *r; std::vector<ptr> vec{ptr{p},ptr{q},ptr{r}}; or ptr p, q, r; std::vector<ptr> vec{std::move(p),std::move(q),std::move(r)};
This is in response to national body comment DE 8, which is has a defect number 1125 (Unclear definition of “potential constant expression”). THe question boils down to answering if the word "arbitrary" means "there exists a value for which the result is a constant expression" or "for all possible values, the result needs to be a constant expression". If we choose the latter answer functions like constexpr int f(int x, int y){ return x + y; } become invalid. Nearly every constexpr function is invalid. If we choose the former option we render all functions like constexpr int f2(bool v) { return v ? throw 0 : 0; } valid. There are possibly some middle-ground solutions, however, unless there exists some serious technical difficulty, I would propose to adapt a solution that allows throwing from constexpr function; it is very useful for reporting errors at both compile-time and runtime. Consider this example.
constexpr int dayOfMonth( int d ) { return (d < 1 || d > 31) ? (throw InvalidDayOfMonth, 0), d; }
This function at compile-time works for arguments between 1 and 31, and fails to compile for other values (almost a static_assert). At run-time it works for arguments between 1 and 31 and throws exception for other values. In contrast, for the other interpretation of the word "arbitrary" we have no mechanism for communicating errors neither at compile time, nor at run-time.
If the throw example works, it enables us to implement compile-time arbitrary string processing, the feature that variadic templates and user-defined literals failed to deliver. The method is briefly described here : https://groups.google.com/group/comp.std.c++/browse_thread/thread/718da390a710e9cc?hl=en