【问题标题】:Casting a function pointer into a noexcept specified function pointer将函数指针转换为 noexcept 指定的函数指针
【发布时间】:2016-06-03 17:38:33
【问题描述】:

假设我有这些声明:

using fp_type = void(*)();
using fp2_type = void(*)() noexcept;

void func(){}
fp_type fp(func);

fp2_type(fp) 的演员阵容是否良好?反过来(将 noexcept 指定的函数指针转换为没有 noexcept 说明符的函数指针)?

【问题讨论】:

  • “反过来”很好,实际上是一种隐式转换。 fp2_type(fp) 看起来应该是 reinterpret_cast
  • 有趣的问题。注意:“15.4.12 异常规范不被视为函数类型的一部分”
  • 实际上,这是在他们将异常规范作为类型系统的一部分之前还是之后(即,这是针对 C++1z 还是 C++14/earlier)?
  • 我在这里问了一个关于 C++17 的非常相似的问题:stackoverflow.com/questions/57596276/…

标签: c++ function-pointers noexcept


【解决方案1】:

这在 C++14 及更早版本中格式不正确:

using fp2_type = void(*)() noexcept;

由于 N4140 [except.spec]/2:

exception-specification 不得出现在 typedef 声明或 alias-declaration 中。

所以我假设问题是针对 C++1z,其中异常规范是类型系统的一部分。


[conv.fctptr]/1:

“指向noexcept函数的指针”类型的纯右值可以转换为 “指向函数的指针”类型的纯右值。结果是一个指向 功能。

因此,void (*)() noexcept 可以(隐式)转换为 void (*)()

[expr.static.cast]/7:

任何标准转换序列的逆(子句 [conv])不是 包含[(其他各种情况省略)]函数指针([conv.fctptr])的转换,可以进行 显式使用static_cast

[expr.static.cast] 中没有其他内容允许将void (*)() 转换为void (*)() noexcept,因此这不是static_cast 可以执行的转换。

[expr.reinterpret.cast]/6:

函数指针可以显式转换为函数指针 不同类型的。通过a调用函数的效果 指向函数类型 ([dcl.fct]) 的指针与 函数定义中使用的类型未定义。除了那个 将“pointer to T1”类型的纯右值转换为“pointer to”类型 T2”(其中T1T2 是函数类型)并返回其原始类型 产生原始指针值,这种指针的结果 转换未指定。 [注意:另见[conv.ptr]了解更多 指针转换的详细信息。 ——尾注]

所以reinterpret_cast 可以执行此转换。

由于fp2_type(fp) 等价于C 风格的演员(fp2_type) fp ([expr.type.conv]/1) 和since C-style casts do a reinterpret_cast when static_cast is not possible(为简单起见忽略const_cast,因为它与这里无关),fp2_type(fp) 是一个很好的形成reinterpret_cast。但是,这种类型转换的结果只能被使用,只能将其转换回去。

【讨论】:

  • 相关问题,如果您可以将 noexcept 函数转换为常规函数,您现在可以对 const 和 volatile 成员函数指针做同样的事情(反之亦然)吗?
  • 在 c++11/14 下有一个解决转换问题的方法。用 noexcept 说明符声明一个函数,如 void f() noexcept;然后像 decltype(&f)(fp) 一样投射。也许将此添加到您的答案中?
猜你喜欢
  • 2012-11-21
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 1970-01-01
相关资源
最近更新 更多