Using noexcept

Update. This post has been updated based on the input provided by Rani Sharoni, the key author of the noexcept feature, in this post on comp.lang.c++.moderated. Previous guidelines for using noexcept were far too limiting. I also added a section describing the difference between noexcept and throw(). Even if you have already read this article you may want to do it again, as it has changed significantly. The changes have been highlighted with the blueish color.

Recent discussions in comp.lang.c++.moderated and comp.std.c++ (here are the links) indicate that C++ community is lacking the information on the new noexcept feature. While we know it is in C++11, there is lots of confusion on how it works, what it is good for, why it works the way it does, and how we should use it safely and effectively. In this post I try to come up with guidelines on how to use noexcept. They are based on C++ Committee papers I was able to collect on the subject, and experts’ replies in discussion groups.

History

It all started from the observation made by David Abrahams and Douglas Gregor that some types that used to work fine in C++03 might automatically and silently obtain a throwing move constructor in C++11, and that some operations on STL containers that used these throwing moves would automatically and silently fail to provide the strong exception safety guarantee. For detailed description of this issue see article “Exceptionally Moving” in C++Next. The problem has been also described in N2855. The document provided the first solution to the problem. A noexcept specifier placed in front of function’s signature indicating that the function is intended not to throw exceptions:

noexcept void swap( T& lhs, T& rhs );

Compiler would check the function definition and report an error if the function was invoking a potentially throwing operation. Move constructors (and destructors) would be implicitly declared as noexcept and therefore compiler would statically check if move constructors (and destructors) were really not throwing exceptions. If for some reason you needed your move constructor or destructor to be able to throw exceptions, you would have to explicitly declare the function as throwing:

ScopeGuard::~ScopeGuard() throw(...);

Such throwing move constructors would not be considered for optimization opportunities in STL containers and thus the original problem would be solved.

Note that noexcept destructors do not help the original problem of throwing moves. But since the changes in throwing detection area were made anyway, it was decided to provide a more general solution that would solve some other long outstanding problems: throwing destructors, unimplemented and unsuccessful exception specifications, missing no-throw optimizations.

Just statically forcing that noexcept functions do not call directly or indirectly any code that might potentially throw would be too restrictive. There are functions that never throw but simple static analysis classifies them as throwing. Consider the following:

double sqrt( double x ) {
    if( x < 0 ) throw InvalidInput();
    return nofail_sqrt(x);
}

double sqrt_abs( double x ) {
    return sqrt(abs(x));
}

Function sqrt_abs never throws because the call to abs eliminates all input to sqrt that could cause a throw. However simple static analysis says that that sqrt_abs might throw because it calls a function that might throw. To solve the problem the proposal also offered a noexcept block:

noexcept double sqrt_abs( double x ) {
    noexcept {
        return sqrt(abs(x));
    }
}

Anything inside the block, even if potentially throwing, should not stop the compilation of a noexcept function. This technically allowed the possibility that a noexcept function could still throw: this would trigger an undefined behavior. In addition, current exception specifications in C++03 were to be deprecated.

Then, Rani Sharoni proposed a different solution. It was presented at Santa Cruz meeting in 2009: N2983. Its main difference in approach was that, rather than banning throwing move operations, it added the ability for STL containers to detect whether move operations could throw and if so, resort to using copy operations. This selection was performed using the new function template std::move_if_noexcept. While custom move operations are not forced to be noexcept, an another proposal (N2953) made implicitly generated moves automatically labelled as noexcept wherever it was possible to verify that they are non-throwing.

Another significant change in the second proposal was that compiler was no longer statically checking if a noexcept functions really do not throw exceptions. noexcept became more like throw() in C++03: it was just a declaration in the function’s interface that you intend your function not to throw, but you could still throw at the risk of triggering an undefined behavior. While this decision is controversial, it was chosen because:

  1. It had been already implemented on a production-class compiler (Microsoft’s non-standard-conforming implementation of throw()), and proved successful.
  2. The noexcept block for locally disabling the static check was not good enough for all situations, for instance it was not suitable for disabling the check in constructors’ initialization lists.
  3. Requiring an additional block in function code was too inconvenient. Additional scope could require rethinking the scopes of local variables and unnecessarily make the functions longer. Consider qsrt_abs example. We incorrectly included function abs into the noexcept block; but if we did not do it, we would have to introduce an automatic variable to store the intermediate result, and our one-liner would become a four-liner.
  4. Such static check was too restrictive in case of destructors; lots of current C++03 code would be broken.

As a replacement, N2983 offered a noexcept operator that allows the programmer to statically (at compile-time) check if a given expression is a potentially throwing one. Thus, compile-time checks for noexcept violation can be performed on demand rather than being always forced. Similarly, a couple of type traits, like nothrow_move_constructible and nothrow_move_assignable have been added to enable further compile-time querying for no-throw properties.

Third important thing that N2983 offered was the solution to the often encountered problem of exception specifications: how to annotate function templates that may or may not throw exceptions depending on the type(s) they are instantiated with. noexcept specification now accepted a boolean parameter that could be computed at compile-time indicating if a function may throw or not:

template< typename T >
void swap( T& lhs, T& rhs )
noexcept( is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value )
{
    //...
}

Upon next committee’s meeting in Pittsburgh in 2010 the revised version of the proposal, N3050, introduced one important change: the violation of noexcept specification now would result in calling std::terminate and the program would have the freedom to not unwind the stack, or only partially unwind it from the place of an offending throw to the noexcept boundary. This guarantees that the exception will not get out of noexcept function (as it might have been the case with undefined behavior), while still allowing compiler no-throw optimizations. This decision was controversial, and you can see an interesting discussion on the design choices in N3081. One of the main objections was that since throwing from noexcept function has well-defined semantics (calling std::terminate), doing so is perfectly correct, and the compiler cannot reject the following code, even though it can see it is plainly wrong.

void DoSomethingUseful ();

void LaunchApplication() noexcept {
    throw "CallTerminate";
}

int main() {
    std::set_terminate( &DoSomethingUseful );
    LaunchApplication();
}

This is not as serious as it might sound at first, as the compiler is always allowed to report a warning during the compilation that the noexcept is likely to be violated.

Another important objection is that typically in testing mode library functions that impose some preconditions on their arguments (e.g., std::vector::front requires that the vector is not empty) may wish to validate them and report any violations, and the best way of reporting such violation (although not the only one) is to throw a special exception. Using undefined behavior or implementation-defined behavior in place of std::terminate would allow the compilers to still std::terminate the program in most of the cases while allowing different behavior in special cases. This is well described in N3248.

Third objection was that requiring the program to check for exception specification violation to be able to tell when to call std::terminate would require compiler to insert additional code and make the function run slower compared to the solution with undefined behavior. However it appears to be possible to implement a zero-overhead and still optimized code even with std::terminate requirement when noexcept functions are implemented by calls to only other noexcept functions and language primitives (like ints or pointers) that are known not to throw:

void fun1() noexcept {
    int i = 0;    // noexcept
    int * p = &i; // noexcept
    p = nullptr;  // noexcept
}

void fun2() noexcept {
    fun1();
    fun1();
}

int main() {
    std::unique_ptr p( new int(1) );
    fun2();
    // (*) 
}

Note that at (*) the compiler does not need to put any exception checking code and can even just put a call to p‘s destructor in the code, rather than registering the destructor for stack unwinding. On the other hand, in function fun2, compiler does not need to add additional code for noexcept violation checks because it knows all the calls inside fun2 are noexcept. Similarly in fun1, no check for noexcept violation is necessary. Thus, in the entire program that is using noexcept functions in such a propagating way, compiler does not need to add any safety-checking code. This is not the case, however, if you call a potentially throwing functions inside noexcept functions, e.g. in sqrt_abs situation, where you cannot statically check the no-throw guarantee. In such cases some violation checking code will be added.

If the noexcept feature appears to you incomplete, prepared in a rush, or in need of improvement, note that all C++ Committee members agree with you. The situation they faced was that a safety problem with throwing move operations was discovered in the last minute and it required a fast solution. The current solution does solve the problem neatly: there will be no silently generated throwing moves that will make STL containers silently break contracts. Apart from that, other usages of noexcept are yet to be thought over and corrected. While the final shape of C++11 is fixed, noexcept is still evolving and will be improved in the next standard versions. The areas of improvement will likely include:

  1. Static checking of no-throw guarantee, with an improved tool for locally disabling the check.
  2. Improved deduction of noexcept specification wherever the compiler is able to do that (see N3227).
  3. Not require the template authors to specify long and unreadable exception specifications in function declarations, including the funny double noexcept syntax (See N3207). The following is a monstrous example that everyone would like to avoid.
template <class T1, class T2>
struct pair {
    // ...
    constexpr pair() noexcept(
        is_nothrow_constructible<T1>::value &&
        is_nothrow_constructible<T2>::value );

    pair(const pair&) = default;

    pair(const T1& x, const T2& y) noexcept(  
        is_nothrow_constructible<T1, const T1&>::value &&
        is_nothrow_constructible<T2, const T2&>::value );
    //...
    void swap(pair& p) noexcept( 
        noexcept(swap(first, p.first)) &&
        noexcept(swap(second, p.second)));
};

noexcept vs. throw()

One could fairly ask what, in the end, the difference is between noexcept specification and good old throw(). In many aspects they have the same behavior: noexcept operator and ‘nothrow traits’ will equally well detect the no-throw property of the function, regardless if it is declared with noexcept or throw(). As a consequence, the compiler will be able to apply the same no-throw-based optimizations in either variant, for the normal program flow (i.e. as long as no exception violates the no-throw barrier). std::move_if_noexcept will also work equally fine for either.

There are however important differences. In case the no-throw guarantee is violated, noexcept will work faster: it does not need to unwind the stack, and it can stop the unwinding at any moment (e.g., when reaching a catch-all-and-rethrow handler). It will not call std::unexpected. Next, noexcept can be used to express conditional no-throw, like this: noexcept(some-condition)), which is very useful in templates, or to express a may-throw: noexcept(false).

One other non-negligible difference is that noexcept has the potential to become statically checked in the future revisions of C++ standard, whereas throw() is deprecated and may vanish in the future.

Guidelines for using noexcept

Given all the above background we can try to formulate guidelines for when to use noexcept. First and most important one, if you are concerned about reduced performance, or about the risk of calling std::terminate, or you are just not sure about the new feature, or if you have doubts whether you should make your function noexcept or not, then just do not annotate your functions with noexcept at all. The basic idea behind exception mechanism is that practically every function may throw. Your code must be prepared anyway that exceptions get thrown, sometimes even when you may not expect it. Even functions compiled with old C compiler may throw exceptions (because they in turn may call components written in C++). Just let your functions throw.

This does not mean that noexcept is useless. Compiler will annotate implicitly generated member functions of your classes (constructors, copy and move assignments and destructor) with noexcept, as appropriate, and STL components will be querying for this annotation. The feature will enable significant optimizations (by using move constructors) even though you will not see a single noexcept keyword. And when compiler annotates functions with noexcept it does it correctly (except for destructors), so there is no risk that some noexcept move constructor will throw.

It is important to distinguish two situations where functions do not throw exceptions (even in C++03, if you were able to statically inspect the program). First, because it just so happens that you didn’t need to use any throwing or potentially throwing operation to implement the function this time. For an example consider this function.

int sine( int a, int b ) 
{
    return a / sqrt(a * a  + b * b);
}

Integer operations do not throw, square root of a positive number is always well defined (even if it is out of range it will not throw). But the users of sine do not benefit from the fact that it does not throw. They will still be prepared that it might. And you may in the future change the implementation so that it uses an operation that might throw (e.g. on overflow). For this type of functions it is not recommended to annotate them with noexcept because noexcept is in some sense a part of function’s interface. If you commit to it, it will be difficult (if possible) to change it later, when there is a need to throw from the function. On the other hand users of such function (computing sine wave in our example) do not benefit much from the no-throw guarantee.

One additional cost of annotating function as noexcept that needs to be bore in mind is that we are not really declaring that our function does not throw exception: we only declare that we want the program to call std::terminate when we throw. Note that if one day you decide that your function will eventually throw, the compiler might not remind you that you forgot to remove the noexcept specification.

If you insist on using noexcept in those situations, the advice for you is to make your function very small, so that you can easily convince yourself that the function has no way of throwing an exception. You can also use noexcept operator inside your function to statically check if the expressions you use really do not throw exceptions:

template< typename T >
T sine( T const& a, T const& b ) noexcept
{
    static_assert( noexcept( T(a / sqrt(a * a  + b * b)) ), "throwing expr" );
    return a / sqrt(a * a  + b * b);
}

static_assert combined with noexcept operator works almost like statically checked no-throw specification if you carefully check all expressions in your function. However, it may be tricky to check all expressions because some of them are invisible. In the example above, we forgot check if the destructors of types in use may throw exceptions. Type T may not be the only type whose destructor we are calling: decltype(T * T) may not be T. Also, for constructors, the default initialization of sub-objects may go unnoticed.

Another guideline for you, suggested in N3248, is not to annotate your function with noexcept if it is not well defined for all possible input values, i.e. if it imposes some preconditions on its inputs. For instance, the above example does have such precondition: it requires that sqrt(a * a + b * b) != 0. This means that one day you will want to change your function to:

template< typename T >
T sine( T const& a, T const& b ) noexcept
{
    static_assert( noexcept( T(a / sqrt(a * a  + b * b)) ), "throwing expr" );
    BOOST_ASSERT( sqrt(a * a  + b * b) != 0 );
    return a / sqrt(a * a  + b * b);
}

And one day, while unit-testing, you will want to customize the behavior of BOOST_ASSERT so that it throws special exception test_failure. But throwing this exception will then not work because the program is required to std::terminate in such case.

We said there are two situations where functions do not throw exceptions. The second one is when we intend our function to provide a no-fail guarantee or a no-throw guarantee. The difference between the two guarantees is not trivial. A no-fail guarantee indicates that the function will always succeed in doing what it is supposed to. Such functions are needed by other functions to provide a strong (commit-or-rollback) guarantee. A no-throw guarantee is weaker. It indicates that in case the function fails to do its job, it must not throw exceptions: it might use an error code or some other technique for signalling error, or it may just conceal the fact that it failed. This guarantee is required of functions that are called during stack unwinding where some exception is already being handled and throwing a second one makes the unwinding process to fail. These functions include all destructors, constructors of objects representing exceptions, an conversion operators that return exceptions.

For this cases annotating functions with noexcept makes sense. Note that your functions in C++03 already provide no-fail or no-throw guarantees. And the additional keyword doesn’t make the guarantees any stronger. The reason for noexcepting your functions is that in case some programmer that uses them wants, in turn, to provide a no-fail/no-throw guarantee for his function, he will likely want to check your functions with noexcept operator. Also the compiler will be checking for non-throwing specification in order to perform run-time optimizations. Good candidates for such no-fail functions include:

  • memory deallocation functions,
  • swap functions,
  • map::erase and clear functions on containers,
  • operations on std::unique_ptr,
  • other operations that the aforementioned functions might need to call.

In case you are not sure if your function is supposed to or might be suspected of providing a no-fail/no-throw guarantee, just assume it is not: do not annotate it with noexcept. You can always safely add the noexcept later, if need be, because you will be only making your guarantees stronger. The inverse is not possible: declaring the function as noexpect is a commitment to your users that they will be relying on.

Next, big performance optimizations can be achieved in containers like STL vector when your type’s move constructor and move assignment are annotated with noexcept. When STL utility std::move_if_noexcept detects that your moves do not throw it will use these safe moves rather than copies for some operations (like resize). This, in case of containers storing millions of elements, will enable huge optimizations. std::move_if_noexcept may not be the only such optimization tool. Hence the next advice: use noexcept specification when you want noexcept operator or one of the following std traits to work:

  • is_nothrow_constructible,
  • is_nothrow_default_constructible,
  • is_nothrow_move_constructible,
  • is_nothrow_copy_constructible,
  • is_nothrow_assignable,
  • is_nothrow_move_assignable,
  • is_nothrow_copy_assignable,
  • is_nothrow_destructible.

Very occasionally there may be a need to annotate your function with noexcept(false). For normal functions noexcept(false) specification is implied, but it is not the case for destructors. In C++11 destructors, unless you explicitly specify otherwise, have noexcept(true) specification. There exists a wide consensus in C++ community that destructors shouldn’t throw, however there might exist situations where you still need to be able to throw from destructors. In this case you will need to either annotate your destructor with noexcept(false) or derive your class from another class that already declares a throwing destructor.

The following is a useful tool that uses noexcept specification to implement a no-fail swap function. It builds atop std::swap, which in C++11 is implemented somewhat different:

template< typename T >
void std::swap( T & a, T & b )
noexcept( is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value )
{
    T tmp( move(a) );
    a = move(b);
    b = move(tmp);
}

The thing worth noting is that the std::swap is noexcept iff T’s move constructor and move assignment are noexcept. One, but not the only, purpose of function swap is to enable a “modify-the-copy-and-swap” idiom or its special case, “copy-and-swap” idiom, in order to provide a strong exception safety guarantee. In order for this idiom to work we need our swap to provide a no-fail guarantee. Hence the idea of marking swap noexcept wherever possible. On the other hand, for other usages of swap, it does not need to provide no-fail guarantee, and for some types this guarantee is not feasible. Given that, we can use the conditional noexcept flag of std::swap to implement our no-fail version of swapping function:

template< typename T >
void nofail_swap( T & a, T & b ) noexcept
{
    using std::swap;
    static_assert( noexcept(swap(a, b)) ), "throwing swap" );
    swap(a, b);
}

This function should be preferred for implementing “modify-the-copy-and-swap” idiom. Function nofail_swap has the special property: it either does not throw, or the program fails to compile.

Finally, a word of caution for programmers putting moveable but not copyable types, such as std::unique_ptr, or std::thread, into STL containers. Function template std::move_if_noexcept is defined as follows in C++11.

template< class T > 
typename conditional<
    !is_nothrow_move_constructible<T>::value 
    && is_copy_constructible<T>::value,
        T const&, 
        T &&
>::type move_if_noexcept( T& x ) noexcept;

The condition with double negation is somewhat hard to read but it effectively says that we chose to move iff we have a no-throw move or we do not have a copy. That is, if we do not have a copy, we choose to move regardless if the move throws or not. If you use objects of such types in sequence containers std::vector or std::dequeue, note that some operations that typically provide strong exception safety guarantee will now only provide basic guarantee (resize), whereas some other operations may result in unspecified behavior in case any element throws exception while being moved (insert, emplace, emplace_back, push_back, and dequeue-speciffic emplace_front and push_front).

About these ads
This entry was posted in programming and tagged , . Bookmark the permalink.

15 Responses to Using noexcept

  1. Martin Ba. says:

    Since I did this anyway a while back, I might just as well add it here …

    C++ noexcept Keyword trail
    ==========================

    [ N2855 - Rvalue References and Exception Safety
    date: 2009-03-23
    authors: Douglas Gregor, David Abrahams

    > Proposed Solution
    > ...
    >
    > The noexcept Specifier
    >
    > We propose the addition of a new declaration specifier,
    > noexcept, that indicates that the function it applies to
    > does not throw any exceptions.
    > ...
    >
    > The noexcept Block
    >
    > Statically checking that the body of a function does not throw
    > any exceptions can reject as ill-formed certain programs that
    > are careful to avoid throwing exceptions. ...
    > To address this problem, we propose the addition of a noexcept
    > block, ...
    > The noexcept block states that no exceptions will be thrown by
    > the code within its compound statement. An exception that
    > escapes from a noexcept block results in undefined behavior.
    >
    ]

    [ N3103 - Security impact of noexcept
    date: 2010-08-23
    Authors: David Kohlbrenner, David Svoboda, Andrew Wesie
    ]

    [ N3248 - noexcept Prevents Library Validation
    date: 2011-02-28
    Authors: Alisdair Meredith (ameredith1@bloomberg.net)
    John Lakos (jlakos@bloomberg.net)

    > Abstract
    >
    > The noexcept language facility was added at the Pittsburg meeting
    > immediately prior to the FCD to solve some very specific problems
    > with move semantics. This new facility also addresses a
    > long-standing desire for many libraries to flag which functions
    > can and cannot throw exceptions in general, opening up
    > optimization opportunities. (...)
    ]

    [ N3114 - throw() becomes noexcept
    date: 2010-08-10
    Author: J. Daniel Garcia josedaniel.garcia@uc3m.es

    > During the Rapperswil meeting the Library Working Group decided
    > to change the empty dynamic exception specifications in the
    > librrary to the noexcept specification in the standard library.
    > There was unanimous consent about this change. This paper
    > presents proposed wording for this set of changes. The paper
    > addresses National Body comments CH 16 and GB 60.
    ]

    [ N3148 - throw() becomes noexcept (Version 2)
    date: 2010-10-14
    Author: J. Daniel Garcia (josedaniel.garcia@uc3m.es)

    > Since N3114 the following changes have been made:
    > * Minor editorial adaptations to the latest working
    > draft (N3126).
    > * Removed reference to set_unexpected, which is now
    > deprecated.
    > * Updated restrictions on exception handling for C
    > and C++ libraries.
    > * Corrected adding noexcept to defaulted members, which
    > is not allowed by language.
    > * Revised throw() specifications in chapter 3.
    ]

    [ N3149 - From Throws: Nothing to noexcept
    date: 2010-10-14
    Author: J. Daniel Garcia

    > During the Rapperswil meeting the Library Working Group decided
    > to revise the library to change specifications stating Throws:
    > Nothing to specify noexcept This paper presents proposed wording
    > for this change. However, it does not go further than removing
    > Throws: Nothing. For example, it does not eliminate cluases of
    > the form Throws: Nothing unless ... and similiar clauses.
    ]

    [ N3195 - From Throws: Nothing to noexcept (version 2) ]

    [ N3155 - More on noexcept for the language support library ]
    [ N3156 - More on noexcept for the diagnostics library ]
    [ N3157 - More on noexcept for the General Utilities Library ]

    [ N3166 - Destructors default to noexcept
    date: 2010-10-13
    Author: David Svoboda (svoboda@cert.org)

    > During the Rapperswil meeting, WG21 discussed the prospect of
    > having destructors with no explicit exception specification
    > default to noexcept(true). This was proposed informally by
    > national body comments FI 17 and GB 40. The committee seemed
    > favorable to entertaining such a prospect.

    > Having destructors default to noexcept improves the overall
    > security of a program. A destructor that throws an exception is
    > likely to cause unexpected termination, but only during stack
    > unwinding associated with another exception being thrown and
    > caught. If such a destructor is noexcept, then the destructor's
    > throw causes immediate program termination, whether or not it is
    > being executed during exceptional stack unwinding. Thus this change
    > serves to increase the abnormal termination rate of programs with
    > throwing destructors (that also lack throw() or noexcept clauses).
    > This will serve to call attention to these destructors, where they
    > can be modified, either with a throws() or noexcept clause, or a
    > redesign. This will result in clearer code that terminates less
    > often.
    ]

    [ N3167 - Delete operators default to noexcept ]

    [ N3180 - More on noexcept for the Strings Library ]

    [ N3187 - More on noexcept for the Containers Library ]

    [ N3202 - To which extent can noexcept be deduced?
    date:
    Author: Bjarne Stroustrup

    > Abstract If we fail to deem a function noexcept even though it
    > doesn’t throw the worst that can happen is that sub-optimal, but
    > still correct, code will be executed. Thus, we should craft the
    > simplest rules that render the highest number of functions that
    > does not throw noexcept, while never implicitly make throwing
    > code noexcept. Given the rules suggested here, a noexcept
    > function can only throw if a programmer specifically marked a
    > throwing function noexcept.

    ! > First: in general we cannot know if a function throws - that
    ! > would require (perfect) flow analysis (and in the worst case
    > solving the halting problem). Second: we cannot build systems
    > where an apparently small change in a function forces
    > recompilations of all users. For example:
    > ...
    > Before, f() may have been noexcept; afterwards, it is not: vector
    > may throw.
    >
    ! > I know that some wants static checking of noexcept,
    ! > but I don't and I consider static checking not an option for
    ! > C++0x. I don't even want that discussion now.
    >
    > So, what does noexcept mean? It states what a caller may assume
    > of a called function and if the assumption is wrong (and the
    > called function unexpectedly throws) the program terminates.
    ]

    [ N2983 - Allowing Move Constructors to Throw ]
    [ N3050 - Allowing Move Constructors to Throw (Rev. 1)
    date: 2010-03-12
    Author: David Abrahams, Rani Sharoni, Doug Gregor

    > To date, attempts to solve the problem (including N2855 itself)
    > have taken one basic approach: ban throwing move constructors,
    > and be sure never to generate one.

    > Fortunately, there is a better way. Instead of imposing this
    > burden on every class author, we can deal with the issue more
    > selectively in the operation being move-enabled. There, we know
    > whether a throwing move can disturb existing guarantees. We
    > propose that instead of using std::move(x) in those cases, thus
    > granting permission for the compiler to use any available move
    > constructor, maintainers of these particular operations should
    > use std::move_if_noexcept(x), which grants permission move
    > unless it could throw and the type is copyable.

    > To help the library deduce the correct result for these traits,
    > we propose to add a new kind of exception-specification,
    > spelled:
    >
    > noexcept( integral constant expression )
    >
    > The only impact of such an exception-specification is this: if a
    > function decorated with noexcept(true) throws an exception, the
    > implementation is required to call std::terminate() but it is
    > implementation-defined whether the stack is unwound.
    ]

    [ N3227 - Please reconsider noexcept
    date: 2010-11-23
    Author: Thorsten Ottosen

    > With the adoption of n3050 we have a new keyword noexcept which
    > allows the programmer to tell the compiler (and users) that a
    > function throws no exceptions. This has several good consequence
    > ... However, since the compiler is not allowed to deduce if a function
    > is noexcept, the new feature places a considerable syntactical and
    > maintenance burden on the programmer, so much in fact, that it
    > seriously compromises a major design goal of C++0x: simplicity. We
    > therefore urge the committee to reconsider a compiler deduced
    > noexcept for functions which the definition is either immediate or
    > has been previously seen.
    ]

    [ N3207 - noexcept(auto)
    date: 2010-11-11
    author: Jason Merrill

    > As discussed extensively in reflector traffic and Thorsten and
    > Bjarne's papers, use of noexcept-specifications as specified in
    > the FCD is extremely cumbersome, forcing users to write their
    > functions over again in a mangled form in the
    > noexcept-specification. This is a gratuitous test for whether the
    > user knows what transformation to apply and which pieces of the
    > function matter; as Thorsten writes, "a user-maintained noexcept
    > increases the likelihood that the specification is not correct.
    > In turn, this implies (a) an increased chance that client code
    > terminates unexpectedly, or (b) that optimization opportunities
    > are lost. (Note that providing correct warnings is also
    > undecidable."
    >
    > So, we would like the compiler to generate
    > noexcept-specifications as much as possible.
    >
    > Thorsten and Bjarne's papers argue for implicit deduction of
    > noexcept-specifications, which is certainly attractive; if the
    > compiler can just do the right thing without any programmer
    > intervention, so much the better. Unfortunately, there are some
    > significant problems with this approach.
    ]

    [ N3279 - Conservative use of noexcept in the Library
    date: 2011-03-25
    authors: Alisdair Meredith (ameredith1@bloomberg.net)
    John Lakos (jlakos@bloomberg.net)

    > Motivation
    >
    > The paper N3248 raised a number of concerns with widespread
    > adoption of noexcept exception specifications in the standard
    > library specification, preferring their use be left as a library
    > vendor quality-of-implementation feature until we have more
    > experience.
    >
    > Further discussion at the Madrid meeting, 2011, showed that while
    > the committee shared some of these concerns, it also wanted to
    > promote the use of such exception specifications where they
    > provided a benefit, and did no harm.
    >
    > After some discussion, the following set of guidelines for
    > appropriate use of noexcept in a library specification were
    > adopted. The rest of this paper applies these guidelines to the
    > working paper N3242.
    ]

  2. Sumant says:

    Great post! I liked the idea of nofail_swap. Combining static_assert and noexcept is quite interesting. Silently losing strong exception safety for movable-but-non-copyable types is somewhat unsettling. BTW, here is another great article in June’11 ACCU Overload magazine that explains noexcept gobbledegook: http://accu.org/index.php/journals/c297

  3. Pingback: A tale of noexcept swap for user-defined classes in C++11 | Real Coding!!

  4. Pingback: A tale of noexcept swap for user-defined classes in C++11 | Developer Forums

  5. Pingback: Developer Forums » A tale of noexcept swap for user-defined classes in C++11 » Developer Forums

  6. Pingback: A tale of noexcept swap for user-defined classes in C++11 | Tech Blog

  7. Well written and very informative. Thanks you for putting so much work and analysis into the issue.

  8. tes says:

    “Integer operations never throw”, well there is still division by zero. Otherwise great article! Thanks

  9. @tes: Thank you for the good word. What you say seems to imply that when you divide an int by zero, an exception is thrown. While this expectation is reasonable, and some (or most?) languages really throw in such situations, it is not the case in C++ (or C). In C++ this situation is defined as undefined behavior. This means that compiler vendors are allowed to do whatever they want in this case (abort the program, raise a signal, throw an exception, return a random value, say 9, format your drive C: — probably they will choose the option that gives best run-time performance), and programmers should not make any assumptions on the effect of such operation, because everything may happen.

  10. robdesbois says:

    Thanks for the effort you put into this post Andrzej, it was particularly interesting to see the evolution of this feature.
    Whilst I don’t feel strongly compelled to use noexcept in my code (as for throw()), the case for noexcept move ctors for types going in standard library containers is a good one I’ll be looking to do.

  11. Josh says:

    Awesome post! I probably won’t be using noexcept often in my code, but it is a great thing to know about when looking at other code. And it helps me figure out even better what exactly the compiler is doing.

  12. Pingback: C++ 11 no except | musingstudio

  13. Kagomeko says:

    Thanks for such a detailed description!
    Now I know what this keyword is for. :)

  14. pvblivs says:

    This is looking like a good reason to avoid C++. ISO keeps saying “hey, let’s break all that code out there.” The basic language should have been settled some time ago and they should not be breaking code. As I read your post, they are invalidating the existing throw(type, …) mechanism.

    • Eugene says:

      Can you name a few languages which have backward source compatibility?

      > ISO keeps saying “hey, let’s break all that code out there.”
      You sound like ISO issues new standard as often as Oracle issues new Java version.

      Also, “all that code” is not broken. The exception safety is a big concern for some people but, frankly, I haven’t met one (though perhaps it only shows that my experience is not so big) .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s