15

C++17 makes noexcept part of a function's type. It also allows implicit conversions from noexcept function pointers to potentially throwing function pointers.

void (*ptr_to_noexcept)() noexcept = nullptr;
void (*ptr_to_throwing)() = ptr_to_noexcept;  // implicit conversion

http://eel.is/c++draft/expr.static.cast#7 says that static_cast can perform the inverse of such a conversion.

void (*noexcept_again)() noexcept = static_cast<void(*)() noexcept>(ptr_to_throwing);

Unfortunately, both GCC and clang tell me otherwise: https://godbolt.org/z/TgrL7q

What is the correct way to do this? Are reinterpret_cast and C style cast my only options?

Filipp
  • 1,843
  • 12
  • 26
  • "reinterpret_cast and C style cast" <-- Those two are, more often than not, bugs. At least in *my* experience. – Jesper Juhl Aug 21 '19 at 17:13
  • This question would be more useful if it discarded the confusion about `static_cast` and simply asked “How can I cast this? What’s the danger?”. – Davis Herring Aug 22 '19 at 03:05
  • 1
    I'm intentionally not asking what the danger is. This should be no more dangerous than a `const_cast` where the original object is declared non `const` or a base to derived cast where I know my base reference does in fact refer to a derived object. I'm only concerned that this `noexcept` cast *also* requires all the risk of `reinterpret_cast`. – Filipp Aug 23 '19 at 11:10

1 Answers1

7

You might have skipped over the important part:

The inverse of any standard conversion sequence not containing an lvalue-to-rvalue, array-to-pointer, function-to-pointer, null pointer, null member pointer, boolean, or function pointer conversion, can be performed explicitly using static_­cast.

Currently, a function pointer conversion includes only the conversion from noexcept to potentially throwing. Because you're doing the inverse of a function pointer conversion, static_cast will not work, just like you can't static_cast a pointer to an array, or any of the other conversions listed there.

So yes, reinterpret_cast would be appropriate and also raises the appropriate alarm bells that should come with discarding noexcept.

chris
  • 60,560
  • 13
  • 143
  • 205
  • Could you comment on why that restriction was added to `static_cast`? – Filipp Aug 21 '19 at 17:34
  • 3
    @Filipp, I don't have anything more than speculation, but `static_cast` tends to stay away from more unsafe things and is usually there for when you need a value to be a different type. I picture `noexcept` similar to `const` in this regard where discarding it breaks a promise that was previously made, and this can have drastic consequences for the reader. Most of the other inverses don't make too much sense for C++. The one that has me confused is boolean conversions. Going from bool to a function pointer doesn't make much sense, but compilers allow bool to floating types in `static_cast`. – chris Aug 21 '19 at 17:51