Reputation: 3383
Edit: Here is better code to reproduce. All MSVC versions below 19.20 fail to compile the test.
This problem is related to this SO post. I've noticed my app getting terminated when logic under inplacer
throws an exception.
Here is the code to reproduce:
#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; }
If I build this with MSVC v15.9.20 and run it -- process gets std::terminate()
d. Looks like the problem is in _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>)
It looks like is_nothrow_constructible_v<S, inplacer<...>>
produces false positive which leads to noexcept
declaration, which in turn kills my app when underlying code throws.
P.S. GCC and Clang seem to be working fine.
Upvotes: 0
Views: 222