Title
Rebinding the allocator before calling construct/destroy in allocate_shared
Status
new
Section
[util.smartptr.shared.create]
Submitter
Billy O'Neal III

Created on 2019-06-11.00:00:00, last changed 2019-07-23.15:26:26.

Messages

Date: 2019-07-23.15:26:26

Proposed resolution:

This wording is relative to N4810.

  1. Modify [util.smartptr.shared.create] as indicated:

    [Drafting note: The edits to change pv to pu were suggested by Jonathan Wakely (thanks!). This wording also has the remove_cv_t fixes specified by LWG 3210 — if that change is rejected some of those have to be stripped here.]

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

    -2- Requires: […]

    […]

    -7- Remarks:

    1. (7.1) — […]

    2. […]

    3. (7.5) — When a (sub)object of a non-array type U is specified to have an initial value of v, or U(l...), where l... is a list of constructor arguments, allocate_shared shall initialize this (sub)object via the expression

      1. (7.5.1) — allocator_traits<A2>::construct(a2, pvu, v) or

      2. (7.5.2) — allocator_traits<A2>::construct(a2, pvu, l...)

      respectively, where pvu is a pointer of type remove_cv_t<U>* pointsing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_shared such that its value_type is remove_cv_t<U>.

    4. (7.6) — […]

    5. (7.7) — When a (sub)object of non-array type U is specified to have a default initial value, allocate_shared shall initializes this (sub)object via the expression allocator_traits<A2>::construct(a2, pvu), where pvu is a pointer of type remove_cv_t<U>* pointsing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_shared such that its value_type is remove_cv_t<U>.

    6. […]

    7. (7.12) — When a (sub)object of non-array type U that was initialized by allocate_shared is to be destroyed, it is destroyed via the expression allocator_traits<A2>::destroy(a2, pvu) where pvu is a pointer of type remove_cv_t<U>* pointsing to that object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_shared such that its value_type is remove_cv_t<U>.

Date: 2019-07-23.15:26:26

[ 2019-07 Issue Prioritiztion ]

Priority to 3 after discussion on the reflector.

Date: 2019-06-11.00:00:00

The new allocate_shared wording says we need to rebind the allocator back to T's type before we can call construct or destroy, but this is suboptimal (might make extra unnecessary allocator copies), and is inconsistent with the containers' behavior, which call allocator construct on whatever T they want. (For example, std::list<T, alloc<T>> rebinds to alloc<_ListNode<T>>, but calls construct(T*) without rebinding back)

It seems like we should be consistent with the containers and not require a rebind here. PR would look something like this, relative to N4810; I'm still not super happy with this wording because it looks like it might be saying a copy of the allocator must be made we would like to avoid…

History
Date User Action Args
2019-07-23 15:26:26adminsetmessages: + msg10498
2019-06-13 19:52:05adminsetmessages: + msg10438
2019-06-11 00:00:00admincreate