C.M.
C.M.

Reputation: 3383

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

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

Answers (1)

C.M.
C.M.

Reputation: 3383

It is a known bug. Fixed in msvc v19.16.

Upvotes: 1

Related Questions