Topic: Contradicting definition of empty shared_ptr on


Author: =?UTF-8?B?RGFuaWVsIEtyw7xnbGVy?=<daniel.kruegler@googlemail.com>
Date: Sun, 24 Jun 2012 00:03:32 -0700 (PDT)
Raw View
Am 23.06.2012 22:13, schrieb Kazutoshi Satoda:
>  20.7.2.2/1 (N3376) says:
>>
>>  A shared_ptr object is empty if it does not own a pointer.
>
>  Please note that it says "own a pointer". This definition was added as
>  the resolution for LWG defect #813.
>  813. "empty" undefined for shared_ptr
>  http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#813
>
>  20.7.2.2.1/9 says about the effect of shared_ptr(nullptr_t p, D d):
>>
>>  Effects: Constructs a shared_ptr object that owns the object p and the
>>  deleter d.
>
>  Please note that it says "owns the object". This was intentionally
>  changed from "the pointer" as a part of resolution for LWG defect #758,
>  to cover nullptr_t case.
>  758. shared_ptr and nullptr
>  http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#758
>
>  Since shared_ptr(nullptr, d) owns an object of type nullptr_t, but does
>  not own a pointer, it is said as "empty" by a strict reading of the
>  above definition.
>
>  This causes a contradiction:
>  20.7.2.2.1/10 sets a postcondition use_count() == 1 on
>  shared_ptr(nullptr, d). But 20.7.2.2.5/7 says the return value of
>  use_count() is "0 when *this is empty".
>
>
>  Proposed resolution:
>  Replace the last 2 words in 20.7.2.2/1
>  ... empty if it does not own a pointer.
>  to
>  ... empty if it does not own an object.

I agree with your analysis, this looks like a library defect to me.

>  Besides that, I want to know if it is (or was) possible or not to define
>  shared_ptr(nullptr) (including some variants with deleter and allocator)
>  is empty.

I assume you mean these constructors:

template<class D>  shared_ptr(nullptr_t p, D d);
template<class D, class A>  shared_ptr(nullptr_t p, D d, A a);

should create empty shared_ptr objects, right?

Note that

constexpr shared_ptr(nullptr_t) : shared_ptr() { }

is already empty by definition.

>  It seems to be less surprising.

I agree that the current state is confusing. But I'm not sure whether
your suggested fix would cause less confusion taking all other
constructors together. Personally I would have preferred that for

template<class Y>  explicit shared_ptr(Y* p);
template<class Y, class D>  shared_ptr(Y* p, D d);
template<class Y, class D, class A>  shared_ptr(Y* p, D d, A a);
template<class Y>  shared_ptr(auto_ptr<Y>&&  r);
template<class Y, class D>  shared_ptr(unique_ptr<Y, D>&&r);

constructed with null pointer values the state would be empty in all cases.

I suspect it is too late for this change, though.

HTH&  Greetings from Bremen,

Daniel Kr  gler


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: Kazutoshi Satoda <k_satoda@f2.dion.ne.jp>
Date: Sun, 24 Jun 2012 23:49:13 -0700 (PDT)
Raw View
Daniel Kr   gler wrote:
>
> Am 23.06.2012 22:13, schrieb Kazutoshi Satoda:

(snip)
>>
>>  Proposed resolution:
>>  Replace the last 2 words in 20.7.2.2/1
>>  ... empty if it does not own a pointer.
>>  to
>>  ... empty if it does not own an object.
>
>
> I agree with your analysis, this looks like a library defect to me.


Yes. I forgot to put "Defect report:" on the subject. Sorry about that.

>>  Besides that, I want to know if it is (or was) possible or not to define
>>  shared_ptr(nullptr) (including some variants with deleter and allocator)
>>  is empty.
>
>
> I assume you mean these constructors:
>
> template<class D>  shared_ptr(nullptr_t p, D d);
> template<class D, class A>  shared_ptr(nullptr_t p, D d, A a);
>
> should create empty shared_ptr objects, right?


That's right.

> Note that
>
> constexpr shared_ptr(nullptr_t) : shared_ptr() { }
>
> is already empty by definition.


I wasn't aware of the delegating constructor at the first post. Thanks.

... it seems also lack noexcept though. unique_ptr(nullptr_t) has
noexcept. Another defect or editorial thing?

> I agree that the current state is confusing. But I'm not sure whether
> your suggested fix would cause less confusion taking all other
> constructors together. Personally I would have preferred that for
>
> template<class Y>  explicit shared_ptr(Y* p);
> template<class Y, class D>  shared_ptr(Y* p, D d);
> template<class Y, class D, class A>  shared_ptr(Y* p, D d, A a);
> template<class Y>  shared_ptr(auto_ptr<Y>&&  r);
> template<class Y, class D>  shared_ptr(unique_ptr<Y, D>&&r);
>
> constructed with null pointer values the state would be empty in all cases.


It would require a runtime check for null pointer for each and probably
more. The design choice seems have been made on Boost design period not
to have such checks.
http://www.boost.org/doc/libs/1_31_0/libs/smart_ptr/shared_ptr.htm#constructors
>
> The postcondition that use count is 1 holds even if p is 0; invoking
> delete on a pointer that has a value of 0 is harmless.

(I can see this note at least through 1.31 to 1.49 (latest). I'm not
 sure the design rationale was really avoiding the runtime checks.)

So I think this confusion is not really a new thing and somewhat
acceptable, but was probably avoidable for really new nullptr_t case.

> I suspect it is too late for this change, though.


I also suspect that. Then I propose to fix just the apparent
contradiction.

--
k_satoda



[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]