This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

### 813. "empty" undefined for `shared_ptr`

Section: 20.3.2.2 [util.smartptr.shared] Status: CD1 Submitter: Matt Austern Opened: 2008-02-26 Last modified: 2016-01-28

Priority: Not Prioritized

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

View all issues with CD1 status.

Discussion:

Several places in 20.3.2.2 [util.smartptr.shared] refer to an "empty" `shared_ptr`. However, that term is nowhere defined. The closest thing we have to a definition is that the default constructor creates an empty `shared_ptr` and that a copy of a default-constructed `shared_ptr` is empty. Are any other `shared_ptr`s empty? For example, is `shared_ptr((T*) 0)` empty? What are the properties of an empty `shared_ptr`? We should either clarify this term or stop using it.

One reason it's not good enough to leave this term up to the reader's intuition is that, in light of N2351 and issue 711, most readers' intuitive understanding is likely to be wrong. Intuitively one might expect that an empty `shared_ptr` is one that doesn't store a pointer, but, whatever the definition is, that isn't it.

[ Peter adds: ]

> Or, what is an "empty" `shared_ptr`?

> - Are any other `shared_ptrs` empty?

>   Yes. Whether a given `shared_ptr` instance is empty or not is (*) completely specified by the last mutating operation on that instance. Give me an example and I'll tell you whether the `shared_ptr` is empty or not.

>   > (*) If it isn't, this is a legitimate defect.

> - For example, is `shared_ptr((T*) 0)` empty?

>   No. If it were empty, it would have a `use_count()` of 0, whereas it is specified to have an `use_count()` of 1.

> - What are the properties of an empty `shared_ptr`?

>   The properties of an empty `shared_ptr` can be derived from the specification. One example is that its destructor is a no-op. Another is that its `use_count()` returns 0. I can enumerate the full list if you really like.

> - We should either clarify this term or stop using it.

>   I don't agree with the imperative tone

>   A clarification would be either a no-op - if it doesn't contradict the existing wording - or a big mistake if it does.

>   I agree that a clarification that is formally a no-op may add value.

> - However, that term is nowhere defined.

>   Terms can be useful without a definition. Consider the following simplistic example. We have a type `X` with the following operations defined:

>   >     X x;
>   >     X x2(x);
>   >     X f(X x);
>   >     X g(X x1, X x2);

>   A default-constructed value is green.
>   A copy has the same color as the original.
>   `f(x)` returns a red value if the argument is green, a green value otherwise.
>   `g(x1,x2)` returns a green value if the arguments are of the same color, a red value otherwise.

>   Given these definitions, you can determine the color of every instance of type `X`, even if you have absolutely no idea what green and red mean.

>   Green and red are "nowhere defined" and completely defined at the same time.

> Alisdair's wording is fine.

Proposed resolution:

Append the following sentance to 20.3.2.2 [util.smartptr.shared]

> The `shared_ptr` class template stores a pointer, usually obtained via `new`. `shared_ptr` implements semantics of shared ownership; the last remaining owner of the pointer is responsible for destroying the object, or otherwise releasing the resources associated with the stored pointer. A `shared_ptr` object that does not own a pointer is said to be empty.