noexcept
suggest change- A unary operator that determines whether the evaluation of its operand can propagate an exception. Note that the bodies of called functions are not examined, so
noexcept
can yield false negatives. The operand is not evaluated.#include <iostream> #include <stdexcept> void foo() { throw std::runtime_error("oops"); } void bar() {} struct S {}; int main() { std::cout << noexcept(foo()) << '\n'; // prints 0 std::cout << noexcept(bar()) << '\n'; // prints 0 std::cout << noexcept(1 + 1) << '\n'; // prints 1 std::cout << noexcept(S()) << '\n'; // prints 1 }
In this example, even though
bar()
can never throw an exception,noexcept(bar())
is still false because the fact thatbar()
cannot propagate an exception has not been explicitly specified. - When declaring a function, specifies whether or not the function can propagate an exception. Alone, it declares that the function cannot propagate an exception. With a parenthesized argument, it declares that the function can or cannot propagate an exception depending on the truth value of the argument.
void f1() { throw std::runtime_error("oops"); } void f2() noexcept(false) { throw std::runtime_error("oops"); } void f3() {} void f4() noexcept {} void f5() noexcept(true) {} void f6() noexcept { try { f1(); } catch (const std::runtime_error&) {} }
In this example, we have declared that
f4
,f5
, andf6
cannot propagate exceptions. (Although an exception can be thrown during execution off6
, it is caught and not allowed to propagate out of the function.) We have declared thatf2
may propagate an exception. When thenoexcept
specifier is omitted, it is equivalent tonoexcept(false)
, so we have implicitly declared thatf1
andf3
may propagate exceptions, even though exceptions cannot actually be thrown during the execution off3
.Whether or not a function is
noexcept
is part of the function’s type: that is, in the example above,f1
,f2
, andf3
have different types fromf4
,f5
, andf6
. Therefore,noexcept
is also significant in function pointers, template arguments, and so on.void g1() {} void g2() noexcept {} void (*p1)() noexcept = &g1; // ill-formed, since g1 is not noexcept void (*p2)() noexcept = &g2; // ok; types match void (*p3)() = &g1; // ok; types match void (*p4)() = &g2; // ok; implicit conversion