21

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
psmears
  • 26,070
  • 4
  • 40
  • 48
AnArrayOfFunctions
  • 3,452
  • 2
  • 29
  • 66
  • Note that `gcc` accept the code with incoherent exception specification... (http://coliru.stacked-crooked.com/a/3e65f6d6a7fc89a8) – Jarod42 Apr 07 '15 at 13:39
  • If it was part of function type, you may have 2 overloads with just exception specification as difference... – Jarod42 Apr 07 '15 at 13:40
  • 2
    You can have 2 overloads with different return type too - but it is not allowed. This won't be either. – AnArrayOfFunctions Apr 07 '15 at 13:41
  • 9
    See [closed CWG issue #92](http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#92) and [N4320](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4320.html) – dyp Apr 07 '15 at 13:47
  • 5
    @dyp You should make that an answer. – Mark B Apr 07 '15 at 14:09
  • @dyp As of April, *"EWG has expressed interest in further exploring this issue, so it has been returned to "extension" status."* This might partly be due to this question :) – Columbo May 11 '15 at 21:18
  • @Columbo Possibly, but isn't it more likely a result of N4320? – dyp May 11 '15 at 21:39
  • @dyp Oh, I thought that paper was written after..... nevermind. Why have you referred to the issue as closed then? (I mean, yeah, it's listed under closed, but the note says it has been returned to extension status) – Columbo May 11 '15 at 21:45
  • @Columbo Since both my comment and the new note under the CWG issue are both from April 2015, it is quite possible that I couldn't have seen it back then. – dyp May 11 '15 at 21:51

2 Answers2

13

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)

Danra
  • 9,546
  • 5
  • 59
  • 117
3

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.

Community
  • 1
  • 1
bartop
  • 9,971
  • 1
  • 23
  • 54
  • I'm not agree with reasoning in your `Low Level` section, because `const` does not change our expectation of the function and it cause new overload – BigBoss Feb 16 '16 at 12:40
  • 1
    There are many implementations where invocation of a function that might throw exceptions would require a compiler to do a little more work than would otherwise be necessary, or refrain from optimizations that would otherwise be possible. If a function pointer always target a function that is going to return normally, is anything gained by requiring a compiler to pessimistically presume it might do otherwise? I could see benefit to requiring that compilers allow a means of invoking a function that isn't qualified `noexcept` through a `noexcept` pointer... – supercat Jan 11 '17 at 16:33
  • 1
    ...which would have defined behavior in cases where the function doesn't *actually* throw exceptions, but I see no downside to having pointers which are or are not `noexcept`-qualified as different-but-compatible types. – supercat Jan 11 '17 at 16:38