Is There an Automatic Noexcept Specifier

Is there an automatic noexcept specifier?

Currently there is none. There is, however, a proposal on that topic, which proposes noexcept(auto) syntax: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4473
The status of this proposal is "needs further work", according to Botond Ballo's "Trip Report: C++ Standards Meeting in Lenexa, May 2015" https://botondballo.wordpress.com/2015/06/05/trip-report-c-standards-meeting-in-lenexa-may-2015/

Further Work. The proposal’s direction is promising, but it is either not fleshed out well enough, or there are specific concerns with one or more design points. The author is encouraged to come back with a modified proposal that is more fleshed out and/or addresses the stated concerns.

...

noexcept(auto), which basically means “deduce the noexcept-ness of this function from the noexcept-ness of the functions it calls. Like return type deduction, this requires the body of the function being available in each translation unit that uses the function. It was brought up that, together with the proposal for making exception specifications part of the type system, this would mean that modifying the function’s body could change the function’s type (again similarly to return type deduction), but people weren’t overly concerned about that.

C++ omitting `noexcept` specifier versus `noexcept(false)`, what is their precise meaning?

By specifying noexcept(true), you claim that the function never throws exceptions. By specifying noexcept(false), or not specifying anything, you do not claim that the function never throws exceptions.

So it's basically your statement (2), but note that for the compiler, that's equivalent to your statement (1). If the compiler is not assured that the function will not throw, it must assume that it can.

The relevant bit of the standard is C++11 15.4/12:

A function with no exception-specification or with an exception-specification of the form noexcept(constant-expression) where the constant-expression yields false allows all exceptions. An exception-specification is
non-throwing if it is of the form throw(), noexcept, or noexcept(constant-expression) where the constant-expression
yields true. A function with a non-throwing exception-specification does not allow any exceptions.

There are only two deviations from that rule. One is destructors—putting no exception specification on a destructor gives the destructor the same exception specification as the default-generated one would have. That is, noexcept(true) if and only if all functions which would be directly invoked from the default-generated destructor are noexcept(true).

The other one are deallocation functions (operator delete)—a deallocation function without an explicit exception specification is treated as noexcept(true).

Specifying noexcept function conditionally

You can use a condition for noexcept, but that condition must be a constant expression. It cannot depend on the value of parameters passed to the function, becaue they are only known when the function is called.

From cppreference/noexcept:

Every function in C++ is either non-throwing or potentially throwing

It cannot be both nor something in between. In your example we could make base a template parameter:

template <int base>
int pow(int exp) noexcept( base < 10)
{
return (exp == 0 ? 1 : base * pow<base>(exp - 1));
}

Now pow<5> is a function that is non-throwing, while pow<10> is a function that is potentially throwing.

C++11, `noexcept` specifier, definition versus declaration

[except.spec]/p4:

If any declaration of a function has an exception-specification that
is not a noexcept-specification allowing all exceptions, all
declarations, including the definition and any explicit
specialization, of that function shall have a compatible
exception-specification.

noexcept(some-constant-expression-that-evaluates-to-false) may be omitted. Anything else must be present in all declarations.

noexcept specifier with default arguments construction

Default arguments are shortcut notations for the caller of function. So, when the function executes, the construction is already complete.

Thus, noexcept should be sufficient.

In the standard [dcl.fct.default] states:

If an initializer-clause is specified in a parameter-declaration this
initializer-clause is used as a default argument. Default arguments will be used in calls where trailing arguments are missing.

Example:
the declaration
void point(int = 3, int = 4);
declares a function that can be called with zero, one, or two arguments of type int. It can be called in
any of these ways:
point(1,2); point(1); point();
The last two calls are equivalent to
point(1,4) and point(3,4) , respectively.

Also there is a note (in [intro.execution] Program execution):

Subexpressions involved in evaluating default arguments (8.3.6) are
considered to be created in the expression that calls the function, not the expression that defines the default
argument

When should I really use noexcept?

I think it is too early to give a "best practices" answer for this as there hasn't been enough time to use it in practice. If this was asked about throw specifiers right after they came out then the answers would be very different to now.

Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain).

Well, then use it when it's obvious that the function will never throw.

When can I realistically expect to observe a performance improvement after using noexcept? [...] Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations.

It seems like the biggest optimization gains are from user optimizations, not compiler ones due to the possibility of checking noexcept and overloading on it. Most compilers follow a no-penalty-if-you-don't-throw exception handling method, so I doubt it would change much (or anything) on the machine code level of your code, although perhaps reduce the binary size by removing the handling code.

Using noexcept in the big four (constructors, assignment, not destructors as they're already noexcept) will likely cause the best improvements as noexcept checks are 'common' in template code such as in std containers. For instance, std::vector won't use your class's move unless it's marked noexcept (or the compiler can deduce it otherwise).

How to use noexcept in C++ or How does it work?

A noexcept specification on a function 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).

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().

For more details, please visit below websites

  • https://akrzemi1.wordpress.com/2014/04/24/noexcept-what-for/
  • When should I really use noexcept?

Edit: Sample source code to illustrate above points.

// whether foo is declared noexcept depends on if the expression
// T() will throw any exceptions, check in compile time
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
}


Related Topics



Leave a reply



Submit