为什么在gcc的is_nothrow_constructible实现中需要static_cast?


11

取自GCC实施type_traits为什么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>()))> {};

这种不一致看起来确实很奇怪
在轨道上进行轻度竞赛

4
您应该在相关的libstdc ++邮件列表上询问类似这样的问题
在轨道上进行的Lightness Races

Answers:


12

如果发明的变量声明,则类型不能从参数列表构造

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

充分形成,并且已知不抛出异常。在复数形式的情况下,这等效于类型转换表达式的格式正确和无格式(无可模除性,请参见LWG 2116

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

但是,在单参数情况下,该表达式T(declval<Args>())被视为强制转换表达式,可以调用const_castreinterpret_cast ; 明确使用会static_cast恢复声明形式的等效性。

作为一个具体示例,请考虑以下类型:

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

在此,static_castB constD&&必须使用转换运算符,但是强制转换表达式可以绕过转换运算符,所以也不例外。因此,忽略static_cast会给带来错误的结果is_nothrow_constructible<D&&, B const>


因此,static_cast需要使用,以便始终将表达式视为direct initialization而不是cast expression
若昂·皮雷斯

1
@JoãoPires是的,是的。它仍然不完全是标准所要求的,因为除了使用noexcept运算符进行声明外,不可能测试所有的声明,但是它要紧密得多。
ecatmur

谢谢您的帮助!:d
若昂·皮雷斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.