Skip to content

Exceptions

Simon Gene Gottlieb edited this page Dec 7, 2020 · 8 revisions

Rules for SeqAn3 on Exception-Safety

  • Always guarantee at least the basic exception guarantee (2)!
  • If you can, enforce the strong exception guarantee (3)
  • move construction, move assignment and swap should always be no-throw

See section Exception-Safety for details on exception safety.

Rules for SeqAn3 for the noexcept specifier

When do we use noexcept:

  • If we can ensure that everything within the function body can never throw
  • If it is critical that the function does not throw (move semantics)
    • Try to always make move construction, move assignment and swap noexcept!
    • Use the noexcept()-operator if necessary
  • If there is a measurable performance gain (tests!)

Note: Since explicitly defaulted constructors are noexcept if they can, do not explicitly declare them noexcept, except if you want to enforce this.

See section The noexcept specifier (C++11) for details on noexcept.

Related issue: #45 Related design discussion: 2020-03-30

Exception-Safety

Safety-Guarantee

  1. none or unknown
  2. basic (invariants of the component are preserved, and no resources are leaked)
  3. strong (if an exception is thrown there are no effects)
  4. no-throw (the code will never ever throw)

The noexcept specifier

Adding noexcept to you function declaration will tell the compiler: This function never throws!

void my_function() noexcept // "will never throw"
{
   // ...
}

Benefits:

  • Ensures the no-throw exception guarantee (see above)

    -> can be used accordingly (e.g. when using it in another function to ensure a strong exception guarantee)

  • The compiler may optimize your code (e.g. efficient move with std::move_if_noexcept)

Pitfalls:

What happens if you throw from a noexcept function? Your program terminates, usually without unwinding the stack.

  • Terminating the program isn't the nicest way to report an error to your user.
  • Terminating prevents any error handling
  • Removing noexcept can break the API

Take home message: Use noexcept if you are sure, avoid if in doubt.

The noexcept operator

If you are not sure if something throws, you can use a conditional noexcept:

template <typename t>
int my_function(t & v) noexcept(noexcept(std::declval<t &>().size()))
{
    return v.size();
}

Which code is noexcept?

  • Functions that are declared noexcept
  • Construction of trivial types (e.g. int)
  • Explicitly defaulted constructor and assignment operator foo() = defaulted; (c++11) are implicitely noexcept and constexpr if they can (see stack overflow which references the standard)

Recommended reading

Clone this wiki locally