【问题标题】:Why is static_cast needed in the gcc's implementation of is_nothrow_constructible?为什么在 gcc 的 is_nothrow_constructible 实现中需要 static_cast?
【发布时间】:2020-01-07 11:28:24
【问题描述】:

取自 type_traits 的 GCC 实现,为什么这里需要 static_cast

template <typename _Tp, typename... _Args>
struct __is_nt_constructible_impl
    : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))> {};

template <typename _Tp, typename _Arg>
struct __is_nt_constructible_impl<_Tp, _Arg>
    : public integral_constant<bool,
                               // Why is `static_cast` needed here?
                               noexcept(static_cast<_Tp>(declval<_Arg>()))> {};

【问题讨论】:

  • 这种不一致似乎很奇怪
  • 你应该在相关的 libstdc++ 邮件列表中提出这样的问题

标签: c++ typetraits libstdc++ static-cast


【解决方案1】:

如果发明变量声明

,则不能从参数列表构造类型
T t(declval<Args>()...);

将是 well-formed 并且是 known not to throw exceptions。在复数参数情况下,这等效于(模 noexcept 可破坏性,请参阅LWG 2116)与type conversion expression 的良构性和非抛出性等价

T(declval<Args>()...)

但是在单参数情况下,表达式T(declval&lt;Args&gt;()) 被视为cast-expression,它可以调用const_cast and reinterpret_caststatic_cast 的显式使用恢复了声明表的等价性。

作为concrete example,考虑类型:

struct D;
struct B { operator D&&() const; };
struct D : B {};

这里从B constD&amp;&amp;static_cast 必须使用转换运算符,但强制转换表达式可以绕过转换运算符,因此 noexcept 也是如此。所以省略 static_cast 会给 is_nothrow_constructible&lt;D&amp;&amp;, B const&gt; 错误的结果。

【讨论】:

  • 所以需要 static_cast 以便表达式始终被视为 direct initialization 而不是 cast expression?
  • @JoãoPires 是的,没错。它仍然不完全符合标准的要求,因为无法使用 noexcept 运算符测试声明的 noexcept ,但它更接近。
猜你喜欢
  • 1970-01-01
  • 2018-05-12
  • 1970-01-01
  • 2017-02-16
  • 2018-10-23
  • 2020-11-08
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
相关资源
最近更新 更多