noexcept specifier (since C++11)
Specifies whether a function will throw exceptions or not.
Contents |
[edit] Syntax
noexcept
|
(1) | ||||||||
noexcept( expression)
|
(2) | ||||||||
noexcept
(
true
)
expression | - | constant expression, contextually convertible to bool |
[edit] Explanation
The noexcept-specification (just like dynamic exception specification) can appear as a part of a lambda declarator or a top-level function declarator when declaring functions, variables, non-static data members of type function, pointer to function, reference to function, or pointer to member function, and also when declaring a parameter or a return type in one of those declarations that in turn happens to be a pointer or reference to function. It cannot appear in a typedef or type alias declaration. void f() noexcept; // the function f() does not throw void (*fp)() noexcept(false); // fp points to a function that may throw void g(void pfa() noexcept); // g takes a pointer to function that doesn't throw // typedef int (*pf)() noexcept; // error The noexcept-specification is not a part of the function type. |
(until C++17) |
The noexcept-specification is a part of the function type and may appear as part of any function declarator. |
(since C++17) |
If any declaration of a function has a noexcept specification that isn't noexcept(false)
, other declarations of the same function have to have the same noexcept-specification. Similar restrictions apply to overriders of a virtual function and to initialization and assignment of pointers to functions (target entity has to have identical or more permissive exception specification).
void f() noexcept; void f(); // error, incompatible exception specifications void g() noexcept(false); void g(); // ok
If a search for a matching exception handler leaves a function marked noexcept or noexcept(true), std::terminate is called immediately.
Inheriting constructors and the implicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, move-assignment operators are all noexcept(true)
by default, unless they are required to call a function that is noexcept(false)
, in which case these functions are noexcept(false)
.
Any user-defined destructor is noexcept(true)
by default, unless the declaration specifies otherwise, or the destructor of any base or member is noexcept(false)
.
Any deallocation function is noexcept(true)
by default, unless the declaration specifies otherwise.
A noexcept-specification of a function is considered to be needed in the following contexts
template<class T> T f() noexcept(sizeof(T) < 4); int main() { decltype(f<void>()) *p; // f unevaluated, but noexcept-spec is needed }
The exception specification of a function template specialization is not instantiated along with the function declaration; it is instantiated only when needed (as defined above). The exception-specification of an implicitly-declared special member function is also evaluated as needed (in particular, implicit declaration of a member function of a derived class does not require the exception-specification of a base member function to be instantiated) When the noexcept-specification of a function template specialization is needed, but hasn't yet been instantiated, the dependent names are looked up and any templates used in the expression are instantiated as if for the declaration of the specialization. |
(since C++14) |
[edit] Notes
One of the uses of the constant expression is (along with the noexcept
operator) to define function templates that declare noexcept
for some types but not others.
Note that a noexcept
specification on a function is not a compile-time check; it is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions. The compiler can use this information to enable certain optimizations on non-throwing functions as well as enable the noexcept
operator, which can check at compile time if a particular expression is declared to throw any exceptions. For example, containers such as std::vector will move their elements if the elements' move constructor is noexcept
, and copy otherwise (unless the copy constructor is not accessible, but a potentially throwing move constructor is, in which case the strong exception guarantee is waived).
[edit] Deprecates
noexcept
is an improved version of throw(), which is deprecated in C++11. Unlike throw(), noexcept
will not call std::unexpected and may or may not unwind the stack, which potentially allows the compiler to implement noexcept
without the runtime overhead of throw().
[edit] Keywords
[edit] Example
// whether foo is declared noexcept depends on if the expression // T() will throw any exceptions template <class T> void foo() noexcept(noexcept(T())) {} void bar() noexcept(true) {} void baz() noexcept { throw 42; } // noexcept is the same as noexcept(true) int main() { foo<int>(); // noexcept(noexcept(int())) => noexcept(true), so this is fine bar(); // fine baz(); // compiles, but at runtime this calls std::terminate }
[edit] See also
noexcept operator | determines if an expression throws any exceptions (since C++11) |
exception specification | specifies what exceptions are thrown by a function (deprecated) |
throw expression | signals an error and transfers control to error handler |
(C++11) |
obtains an rvalue reference if the move constructor does not throw (function template) |