如何在C++17中将抛出异常的函数指针转换为noexcept?

15

C++17将noexcept作为函数类型的一部分。它还允许将noexcept函数指针隐式转换为可能引发异常的函数指针。

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

http://eel.is/c++draft/expr.static.cast#7 表示 static_cast 可以执行这种转换的反向操作。

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

不幸的是,GCC和clang告诉我相反: https://godbolt.org/z/TgrL7q

正确的方法是什么?reinterpret_cast和C语言风格的转换是我唯一的选择吗?


"reinterpret_cast和C风格转换" <-- 这两个在我的经验中往往是错误的。 - Jesper Juhl
如果这个问题不涉及到对 static_cast 的困惑,而是直接问“我该如何进行类型转换?有哪些风险?”那么它会更有用。 - Davis Herring
1
我故意不问危险是什么。这应该不比将原始对象声明为非constconst_cast或从基类到派生类的转换更危险,其中我知道我的基础引用确实是指向派生对象的。我只关心这个noexcept转换还要承担所有reinterpret_cast的风险。 - Filipp
1个回答

7
您可能跳过了重要部分:
任何标准转换序列的逆,不包含左值到右值、数组到指针、函数到指针、空指针、空成员指针、布尔或函数指针转换,都可以使用 static_cast 显式地执行。
目前,函数指针转换仅包括从 noexcept 到潜在抛出异常的转换。因为您正在执行函数指针转换的反向操作,所以 static_cast 不起作用,就像您无法将指针转换为数组或列表中列出的任何其他转换一样。
所以,是的,reinterpret_cast 是合适的,并且也会引发与放弃 noexcept 相应的警报。

你能否评论一下为什么在 static_cast 中添加了那个限制? - Filipp
3
@Filipp,我没有比猜测更多的东西,但static_cast往往会避免更不安全的事情,并且通常存在于当您需要将值转换为不同类型时。在这方面,我认为noexcept类似于const,丢弃它会打破先前的承诺,这对读者可能会产生严重后果。大多数其他逆反操作在C++中并没有太多意义。让我困惑的是布尔转换。将bool转换为函数指针没有太多意义,但编译器允许将bool转换为浮点类型使用static_cast - chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接