Suppose a C++ compiler is compiling a function whose definition is available in the same translation unit as its invocation. Suppose that it does not throw itself nor calls a function that is know to throw. Suppose also no extern C
code is called, nor a numeric division with a potentially-zero value.
Under these assumptions, will the compiler treat the function as noexcept
? If not, are there additional conditions under which noexcept
is inferred?
Specifically, what about super-simple functions such as
void foo() { } /* this one */
class A {
int x_;
public:
x() const { return x_; } /* ... and this one */
}
?
I'd like an answer based only on the standard, foremost, and possibly also what GCC and clang do.
The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.
Explicit instantiations may use the noexcept specifier, but it is not required. If used, the exception specification must be the same as for all other declarations.
If you throw, your program terminates What happens if you throw from a noexcept function? Your program terminates, and may or may not unwind the stack. Terminating program isn't the nicest way to report an error to your user. You would be surprised that most of C++ code might throw.
noexcept operator. (since C++11) The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.
When an exception is thrown from a function that is declared noexcept or noexcept(true), std::terminate is invoked. When an exception is thrown from a function declared as throw() in /std:c++14 mode, the result is undefined behavior.
A template function that copies its argument might be declared noexcept on the condition that the object being copied is a plain old data type (POD). Such a function could be declared like this:
The inner noexcept ist the noexcept operator and the outer the noexcept specifier. The expression noexcept (T (src)) checks in this case if the copy constructor is non-throwing. This is the case for the class Noexcept (2) but not for the class NonNoexcept (3) b ecause of the copy constructor of std::vector that may throw.
Almost all functions are assumed to be potentially throwing unless you explicitly use a noexcept
specifier. The exceptions are for your own definitions of delete
(deallocation functions), and some special member functions: constructors, destructors, and assignment operators. (C++17)
From [except.spec]
If a declaration of a function does not have a noexcept-specifier, the declaration has a potentially throwing exception specification unless it is a destructor or a deallocation function or is defaulted on its first declaration, in which cases the exception specification is as specified below and no other declaration for that function shall have a noexcept-specifier.
Are implicitly noexcept
unless any initialization performed for any member (or a member's member etc) is potentially throwing
Are implicitly noexcept
unless any destructor for a potentially constructed sub-object is potentially throwing.
Are implicitly noexcept
unless any use of assignment within is potentially-throwing.
Here's some sample code that demonstrates the above (clang 6.0.0, gcc 8.0.0):
int foo() { return 1; }
int bar() noexcept{ return 1; }
struct Foo{};
struct Bar{
Bar(){}
};
int main()
{
static_assert(noexcept(bar()));
static_assert(!noexcept(foo()));
static_assert(noexcept(Foo()));
static_assert(noexcept(Foo().~Foo()));
static_assert(noexcept(Foo().operator=(Foo())));
static_assert(!noexcept(Bar()));
Bar b;
static_assert(noexcept(b.~Bar()));
}
Yet another reason to use =default
or allow the compiler to generate its own versions of your special member functions via omission.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With