看起来is_nothrow_constructible_v()在MSVC中被破坏了,我错了吗

Looks like is_nothrow_constructible_v() is broken in MSVC, am I wrong?

本文关键字:坏了 我错了 MSVC nothrow is constructible 看起来      更新时间:2023-10-16

编辑:这里有更好的代码可以重现。所有低于19.20的MSVC版本都无法编译测试。


此问题与此SO帖子有关。我注意到当inplacer下的逻辑抛出异常时,我的应用程序被终止。

以下是要复制的代码:

#include <optional>
struct S{};
S foo() { throw "oh, noes..."; }
template<class F>
struct inplacer
{
F f_;
operator std::invoke_result_t<F&>() { return f_(); }
};
template<class F> inplacer(F) -> inplacer<F>;

int main()
try
{
std::optional<S> v;
v.emplace( inplacer{ []{ return foo(); } } );
return 0;
}
catch(...) { return 1; }

如果我用MSVC v15.9.20构建并运行它——进程得到std::terminate()d。看起来问题出在_Construct_in_place():中

template<class _Ty,
class... _Types> inline
void _Construct_in_place(_Ty& _Obj, _Types&&... _Args)
_NOEXCEPT_COND(is_nothrow_constructible_v<_Ty, _Types...>)                     <----- HERE???
{   // invoke True Placement New to initialize the referenced object with _Args...
::new (const_cast<void *>(static_cast<const volatile void *>(_STD addressof(_Obj))))
_Ty(_STD forward<_Types>(_Args)...);
}
// std::_Construct_in_place<S,inplacer<S <lambda>(void) > >(S & _Obj, inplacer<S <lambda>(void) > && <_Args_0>)

看起来is_nothrow_constructible_v<S, inplacer<...>>会产生假阳性,从而导致noexcept声明,这反过来又会在底层代码抛出时杀死我的应用程序。

p.S.GCC和Clang似乎工作得很好。

这是一个已知的错误。已在msvc v19.16中修复。