3

What is the difference between this:

bool foo(int){return 0;}
void bar()noexcept(foo){}

And

void bar()noexcept(foo(10)){}
  • In the first bar has the same exception specification as foo and the latter may throw so the two are equivalent to noexcept(false). But what about the second version:

    noexcept(noexcept(foo(10)))?

  • Are the two declarations identical?

Itachi Uchiwa
  • 3,044
  • 12
  • 26
  • Well, both should emit a compiler diagnostic since `foo` can't be implicitly converted to a `bool` and `foo(10)` isn't a literal expression (unless you mark `foo` as `constexpr`). Am I missing something? Did you mean to ask about `noexcept(noexcept(foo(10))` instead? – Brian61354270 Oct 31 '21 at 21:08
  • @Brian: I think it doesn't matter the return type or value here when it comes to be an expr passed to `noexcept`: `void f(double){} void bar() noexcept(noexcept(f(.14))){}` will compile although `f(3.14)` returns `void`. Because it is not evaluated. – Itachi Uchiwa Oct 31 '21 at 21:12
  • 8
    `noexcept(f(10))` and `noexcept(noexcept(f(10)))` are very different things – StoryTeller - Unslander Monica Oct 31 '21 at 21:14
  • 3
    As far as `noexcept(foo)`... it doesn't do what you think it does by a country mile. All it does is convert `foo` to a bool. Function names always decay to valid addresses, so the extra bool conversion is always to `true`. That specification is a plain `noexcept` with extra steps. – StoryTeller - Unslander Monica Oct 31 '21 at 21:20
  • @StoryTeller-UnslanderMonica: Yes the first evaluates the expression and which must be constexpr but the latter no. I want to know what is the difference between: `noexcept(foo) and noexcept(noexcept(foo))`? I mean is the function call redundant here? – Itachi Uchiwa Oct 31 '21 at 21:21
  • @StoryTeller-UnslanderMonica: Would you add an answer to explain things a bit better? Thank you. – Itachi Uchiwa Oct 31 '21 at 21:23
  • The later evaluates the constant expression alright. But the expression isn't `foo(10)`, it's `noexcept(foo(10))`. `noexcept` is an operator too, among other roles. `constexpr bool b = noxcept(f(10));` is a valid declaration. – StoryTeller - Unslander Monica Oct 31 '21 at 21:24
  • @StoryTeller-UnslanderMonica FWIW, that sort of conversion (function pointer to bool) isn't allowed in a [converted constant expression](https://en.cppreference.com/w/cpp/language/constant_expression#Converted_constant_expression), which the expression given to `noexcept` is. – Brian61354270 Oct 31 '21 at 21:24
  • @Brian - I'm not up to speed about the latest constraints of constant evalution. While it's true the [conv.bool] is only mentioned as part of integral conversion... this specific case seems possible to make permissible. Maybe a CWG issue I'm unaware of or some such. Dunno. – StoryTeller - Unslander Monica Oct 31 '21 at 21:28

1 Answers1

1

What is the difference between this:

bool foo(int){return 0;}
void bar()noexcept(foo){}

And

void bar()noexcept(foo(10)){}

The difference isn't very important since both are ill-formed. But, let's look at why that is:

First is ill-formed because when foo is contextually convertd to bool, it will first implicitly convert to a pointer to function. Although the pointer is always going to point fo foo and thus the result is always true, such conversion is nevertheless not a constant expression and is thus not allowed in the noexcept specification.

Second is ill-formed because foo is not a constexpr function, so it may not be called in a noexcept specification.


But what about the second version noexcept(noexcept(foo(10)))?

noexcept(foo(10)) is false if the function invoked by the expression foo(10) is potentially throwing, and true if it is noexcept. Thus, this achieves the "copying" of the exception specification. Nearly always this is done when the expression in question is used within the function:

void bar() noexcept(noexcept(foo(10))) {
    bool example = foo(10);
}
eerorika
  • 232,697
  • 12
  • 197
  • 326