Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -4124,7 +4124,7 @@ void __enable_weak_this(const enable_shared_from_this<_Yp>* __e) _NOEXCEPT { - if (__e) + if (__e && __e->__weak_this_.expired()) { __e->__weak_this_.__ptr_ = const_cast<_Yp*>(static_cast(__e)); __e->__weak_this_.__cntrl_ = __cntrl_; @@ -5436,6 +5436,14 @@ shared_ptr<_Tp const> shared_from_this() const {return shared_ptr(__weak_this_);} + _LIBCPP_INLINE_VISIBILITY + weak_ptr<_Tp> weak_from_this() _NOEXCEPT + { return __weak_this_; } + + _LIBCPP_INLINE_VISIBILITY + weak_ptr weak_from_this() const _NOEXCEPT + { return __weak_this_; } + template friend class shared_ptr; }; Index: test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp @@ -18,11 +18,15 @@ // public: // shared_ptr shared_from_this(); // shared_ptr shared_from_this() const; +// weak_ptr weak_from_this() noexcept; // C++17 +// weak_ptr weak_from_this() const noexecpt; // C++17 // }; #include #include +#include "test_macros.h" + struct T : public std::enable_shared_from_this { @@ -32,6 +36,8 @@ struct Z : Y {}; +void nullDeleter(void*) {} + int main() { { // https://llvm.org/bugs/show_bug.cgi?id=18843 @@ -50,4 +56,40 @@ assert(p == q); assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership } + // Test weak_from_this_methods + { + T* ptr = new T; + const T* cptr = ptr; + +#if TEST_STD_VER >= 11 + static_assert(noexcept(ptr->weak_from_this()), "Operation must be noexcept"); + static_assert(noexcept(cptr->weak_from_this()), "Operation must be noexcept"); +#endif + std::weak_ptr my_weak = ptr->weak_from_this(); + assert(my_weak.expired()); + + std::weak_ptr my_const_weak = cptr->weak_from_this(); + assert(my_const_weak.expired()); + + // Enable shared_from_this with ptr. + std::shared_ptr sptr(ptr); + my_weak = ptr->weak_from_this(); + assert(!my_weak.expired()); + assert(my_weak.lock().get() == ptr); + } + // Test LWG issue 2529. Only reset '__weak_ptr_' when it's already expired. + // http://cplusplus.github.io/LWG/lwg-active.html#2529 + { + T* ptr = new T; + std::shared_ptr s(ptr); + { + // Don't re-initialize the "enabled_shared_from_this" base + // because it already references a non-expired shared_ptr. + std::shared_ptr s2(ptr, &nullDeleter); + } + // The enabled_shared_from_this base should still be referencing + // the original shared_ptr. + assert(!ptr->weak_from_this().expired()); + + } } Index: www/cxx1z_status.html =================================================================== --- www/cxx1z_status.html +++ www/cxx1z_status.html @@ -82,7 +82,7 @@ P0226R1LWGMathematical Special Functions for C++17Jacksonville P0220R1LWGAdopt Library Fundamentals V1 TS Components for C++17Jacksonville P0218R1LWGAdopt the File System TS for C++17Jacksonville - P0033R1LWGRe-enabling shared_from_thisJacksonville + P0033R1LWGRe-enabling shared_from_thisJacksonvilleComplete3.9 P0005R4LWGAdopt not_fn from Library Fundamentals 2 for C++17Jacksonville P0152R1LWGconstexpr atomic::is_always_lock_freeJacksonvilleComplete3.9 P0185R1LWGAdding [nothrow-]swappable traitsJacksonville