diff --git a/stl/inc/memory b/stl/inc/memory index 3ddb1c45401..e7ca9c2cfc2 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -4179,7 +4179,15 @@ public: explicit out_ptr_t(_SmartPtr& _Smart_ptr_, _ArgsT... _Args_) noexcept( is_nothrow_constructible_v, _ArgsT...>) /* strengthened */ : _Smart_ptr(_Smart_ptr_), - _Mypair(_One_then_variadic_args_t{}, tuple<_ArgsT...>{_STD forward<_ArgsT>(_Args_)...}) {} + _Mypair(_One_then_variadic_args_t{}, tuple<_ArgsT...>{_STD forward<_ArgsT>(_Args_)...}) { + constexpr bool _Is_resettable = requires { _Smart_ptr.reset(); }; // TRANSITION, DevCom-10291456 + if constexpr (_Is_resettable) { + _Smart_ptr.reset(); + } else { + static_assert(is_constructible_v<_SmartPtr>, "the adapted pointer type must be default constructible."); + _Smart_ptr = _SmartPtr(); + } + } out_ptr_t(const out_ptr_t&) = delete; diff --git a/tests/std/tests/P1132R7_out_ptr/test.cpp b/tests/std/tests/P1132R7_out_ptr/test.cpp index 32cc7e14225..c73a1f0726b 100644 --- a/tests/std/tests/P1132R7_out_ptr/test.cpp +++ b/tests/std/tests/P1132R7_out_ptr/test.cpp @@ -76,8 +76,22 @@ void test_shared_ptr() { assert(*int_ptr == 32); } + // LWG-3734 Inconsistency in inout_ptr and out_ptr for empty case + { + const auto f = [](void** ptr) { *ptr = new int(42); }; + + { + auto temp_adaptor = out_ptr(int_ptr, deleter); + assert(int_ptr.get() == nullptr); + f(temp_adaptor); + } + + assert(count == 2); + assert(*int_ptr == 42); + } + int_ptr.reset(); - assert(count == 2); + assert(count == 3); } template @@ -119,6 +133,19 @@ void test_smart_ptr(Args&&... args) { assert(*int_ptr == 19); } + // LWG-3734 Inconsistency in inout_ptr and out_ptr for empty case + { + const auto f = [](void** ptr) { *ptr = new int(42); }; + + { + auto temp_adaptor = out_ptr(int_ptr); + assert(int_ptr.get() == nullptr); + f(temp_adaptor); + } + + assert(*int_ptr == 42); + } + // LWG-3594 inout_ptr - inconsistent release() in destructor { const auto f = [](int** ptr) { @@ -141,6 +168,10 @@ struct resettable_ptr { explicit resettable_ptr(int* p) : ptr(p) {} + void reset() { + ptr.reset(); + } + void reset(int* p, reset_tag) { ptr.reset(p); } @@ -163,6 +194,7 @@ struct constructible_ptr { unique_ptr ptr; + constructible_ptr() = default; explicit constructible_ptr(int* p) : ptr(p) {} explicit constructible_ptr(int* p, reset_tag) : ptr(p) {}