Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't the "noexcept" specifier part of the function type?

Tags:

I don't get it why? I don't think compatibility should be a problem as functions declared without the specifier actually have it implicitly defined to false. If it's about name mangling - can we just suppose that old one (existing) will imply noexcept(false) and add another new symbol to the mangling for noexcept(true).

This is going to be useful when working with templates as now comparing function type and noexcept specifier should be done seperatly. What I basically mean is this:

int func() noexcept(true), func_1() noexcept(false);

decltype(func) == decltype(func_1); //this now equals true

But on the other hand if we had function assignment by either using pointer or reference then - the noexcept specifier is checked as if it was part of the type:

int (&refFunc)() noexcept(true) = func_1; //target exception specification is not superset of source

int (&refFunc)() noexcept(true) = func; //ok

So for now implementing full function matching should be done by both performing type and noexcept check which is kinda complex:

decltype(func) == decltype(func_1) && noexcept(func()) == noexcept(func_1()); //this now equals false

Imagine if functions have got parameters:

int func(int, double) noexcept(true), func_1(int, double) noexcept(false);

decltype(func) == decltype(func_1) && noexcept(func(int{}, double{})) == noexcept(func_1(int{}, double{})); //this now equals false
like image 916
AnArrayOfFunctions Avatar asked Apr 07 '15 13:04

AnArrayOfFunctions


People also ask

What is Noexcept specifier in C++?

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.

What happens if a Noexcept function throws?

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.

Is Noexcept required?

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.

What happens if a Noexcept true function throws an exception that isn't caught inside the function?

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. No specific function is invoked.


2 Answers

Starting with C++17, the noexcept specifier is a part of the function type.

Reference

The noexcept-specification is a part of the function type and may appear as part of any function declarator. (since C++17)

like image 182
Danra Avatar answered Sep 18 '22 15:09

Danra


C/C++03 compatibility

One of most important C++ basic ideas is backward compatibility with C language and older C++ versions. And it works in most cases. Adding exceptions to function specifiers would deny this idea. There was no noexcept in C++03 and C and it would cause problems with function pointers and so on.

Low level

Let's have a think how function work in low level. They are basically jump with saved (on the stack) return address. They pass arguments and return values also via stack (not always, but let's simplify a bit). So, when you declare a function you actually tell how many bytes function should take from stack and how many it leaves on it. Function declaration is most of all telling the program what to EXPECT NORMALLY from function. Now, knowing that, do exceptions change anything in the information normally passed to/from function? They don't. And I think this is major reason why exceptions aren't part of type.

Edit:

In C++17 noexcept actually became part of the type system so you cannot do this:

void (*p)();
void (**pp)() noexcept = &p; //error here

The rationale behind this decision is, from what I know, allowing better optiization.

like image 40
bartop Avatar answered Sep 18 '22 15:09

bartop