diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index 71099afbf7a4..eb9ad23ba1e3 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -684,8 +684,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Alloc_traits = allocator_traits<_Alloc>; _Alloc __a; _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3548. shared_ptr construction from unique_ptr should move + // (not copy) the deleter _Alloc_traits::construct(__a, __mem, __r.release(), - __r.get_deleter()); // non-throwing + std::forward<_Del>(__r.get_deleter())); _M_pi = __mem; } @@ -1070,9 +1073,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Constraint for construction from unique_ptr: template::pointer> - using _UniqCompatible = typename enable_if<__and_< - __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*> - >::value, _Res>::type; + using _UniqCompatible = __enable_if_t<__and_< + __sp_compatible_with<_Yp*, _Tp*>, + is_convertible<_Ptr, element_type*>, + is_move_constructible<_Del> + >::value, _Res>; // Constraint for assignment from unique_ptr: template diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/lwg3548.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/lwg3548.cc new file mode 100644 index 000000000000..d6ec7b1d0578 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/lwg3548.cc @@ -0,0 +1,16 @@ +// { dg-do compile { target c++11 } } + +#include + +// LWG 3548 +// shared_ptr construction from unique_ptr should move (not copy) the deleter + +struct D +{ + D() { } + D(D&&) { } + void operator()(int* p) const { delete p; } +}; + +std::unique_ptr u; +std::shared_ptr s1(std::move(u)); diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_deleter.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_deleter.cc index f4cf3ddda2e4..d7ca51a4aa6e 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_deleter.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_deleter.cc @@ -58,10 +58,25 @@ test02() VERIFY( D::count == 0 ); // LWG 2415 } +void +test03() +{ + struct D + { + D() = default; + D(const D&) = delete; // not copyable or movable + void operator()(int* p) const { delete p; } + }; + + using namespace std; + static_assert( ! is_constructible, unique_ptr>(), + "Constraints: is_move_constructible_v is true" ); +} + int main() { test01(); test02(); - return 0; + test03(); }