2696. Interaction between make_shared and enable_shared_from_this is underspecified

Section: 20.3.2.2.7 [util.smartptr.shared.create] Status: C++17 Submitter: Joe Gottman Opened: 2016-04-02 Last modified: 2017-07-30

Priority: 2

View other active issues in [util.smartptr.shared.create].

View all other issues in [util.smartptr.shared.create].

View all issues with C++17 status.

Discussion:

For each public constructor of std::shared_ptr, the standard says that constructor enables shared_from_this if that constructor is expected to initialize the internal weak_ptr of a contained enable_shared_from_this<X> object. But there are other ways to construct a shared_ptr than by using a public constructor. The template functions make_shared and allocate_shared both require calling a private constructor, since no public constructor can fulfill the requirement that at most one allocation is made. The standard does not specify that that private constructor enables shared_from_this; therefore in the following code:

struct Foo : public std::enable_shared_from_this<Foo> {};

int main() {
  auto p = std::make_shared<Foo>();
  assert(p == p->shared_from_this());
  return 0;
}

it is unspecified whether the assertion will fail.

[2016-05 Issues Telecon]

Jonathan Wakely to provide updated wording.

[2016-08 Chicago]

Monday PM: Move to Tentatively Ready

Proposed resolution:

This wording is relative to N4582.

  1. Change 20.3.2.2.7 [util.smartptr.shared.create] indicated:

    template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
    template<class T, class A, class... Args>
      shared_ptr<T> allocate_shared(const A& a, Args&&... args);
    

    […]

    -6- Remarks: The shared_ptr constructor called by this function enables shared_from_this with the address of the newly constructed object of type T. Implementations should perform no more than one memory allocation. [Note: This provides efficiency equivalent to an intrusive smart pointer. — end note]