Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -3776,7 +3776,15 @@ _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT; template explicit shared_ptr(_Yp* __p, - typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); + typename enable_if< + __compatible_with<_Yp, element_type>::value && + conditional::value, + __is_array_deletable<_Yp*>, + __is_deletable<_Yp*> + + >::type::value, + __nat + >::type = __nat()); template shared_ptr(_Yp* __p, _Dp __d, typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); @@ -4098,7 +4106,15 @@ template template shared_ptr<_Tp>::shared_ptr(_Yp* __p, - typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) + typename enable_if< + __compatible_with<_Yp, element_type>::value && + conditional::value, + __is_array_deletable<_Yp*>, + __is_deletable<_Yp*> + + >::type::value, + __nat + >::type) : __ptr_(__p), __cntrl_(__allocate_shared(__p)) { Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -4909,6 +4909,32 @@ } #endif +// __is_deleteable + +template +struct __is_deletable +{ + template + static decltype(delete *(_Up*)(0)) test(int); + + template + static false_type test(...); + + static const bool value = !is_same(0))>::value; +}; + +template +struct __is_array_deletable +{ + template + static decltype(delete[] *(_Up*)(0)) test(int); + + template + static false_type test(...); + + static const bool value = !is_same(0))>::value; +}; + _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer.pass.cpp @@ -28,6 +28,25 @@ int A::count = 0; +struct NoDelete +{ + void operator delete (void*) = delete; + void operator delete[](void*) {} +}; + +struct NoArrayDelete +{ + void operator delete (void*) {} + void operator delete[](void*) = delete; +}; + +struct Foo {}; + +struct IntPtrConstructible +{ + IntPtrConstructible(int*) {} +}; + int main(int, char**) { { @@ -63,5 +82,34 @@ assert(A::count == 0); #endif + // overload resolution + { + typedef std::shared_ptr T; + static_assert((!std::is_constructible::value), "" ); + } + { + typedef std::shared_ptr T; + static_assert((std::is_constructible::value), "" ); + } + { + typedef std::shared_ptr T; + static_assert((!std::is_constructible::value), "" ); + } + +#if TEST_STD_VER > 14 + { + typedef std::shared_ptr T; + static_assert(std::is_constructible::value, ""); + } + { + typedef std::shared_ptr T; + static_assert(!std::is_constructible::value, ""); + } + { + typedef std::shared_ptr T; + static_assert(!std::is_constructible::value, ""); + } +#endif + return 0; }