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

### 2218. Unclear how containers use `allocator_traits::construct()`

Section: 24.2.2.1 [container.requirements.general] Status: C++17 Submitter: Jonathan Wakely Opened: 2012-11-27 Last modified: 2017-07-30

Priority: 3

View other active issues in [container.requirements.general].

View all other issues in [container.requirements.general].

View all issues with C++17 status.

Discussion:

Firstly, 24.2.2.1 [container.requirements.general]/7 says a container's allocator is used to obtain memory, but it isn't stated explicitly that the same allocator is used to construct and destroy elements, as opposed to a value-initialized allocator of the same type.

Secondly, 24.2.2.1 [container.requirements.general]/3 says elements "shall be constructed using the `allocator_traits<allocator_type>::construct` function and destroyed using the `allocator_traits<allocator_type>::destroy` function" and 24.2.2.1 [container.requirements.general]/13 defines `CopyInsertable` etc. in terms of an allocator `A` which is identical to the container's `allocator_type`.

The intent of making `construct()` and `destroy()` function templates was that containers would be permitted to use `allocator_traits<A>::construct()` instead of `allocator_traits<allocator_type>::construct()`, where `A` is `allocator_traits<allocator_type>::rebind_alloc<U>` for some other type `U`. This allows node-based containers to store an allocator of the right type for allocating nodes and to use the same object to construct elements in aligned storage within those nodes, avoiding rebinding and copying the stored allocator every time an element needs to be constructed.

It should be made clear that a possibly-rebound copy of the container's allocator is used for object construction.

[2013-03-15 Issues Teleconference]

Moved to Open.

Jonathan: point 2 in the proposed resolution is definitely needed.

[2014-11-28, Jonathan improves wording]

In the first set of edits to paragraph 3 both pieces inserting "`rebind_alloc<U>::`" should be replaced by "`rebind_traits<U>::`"

Otherwise it implies using the allocator's functions directly, but they might not exist and it should be through the rebound traits type.

[2015-05, Lenexa]

STL: You want to permit but not require rebinding?
Wakely: The current wording forces me to use the original allocator, not the rebound one.
STL: Oh, I see. Yeah, we immediately rebind.
Wakely: The edits clarify that we don't use some other allocator. The third diff is because the definitions of EmplaceConstructible/etc. happen with the same types. The diff to the note is because it doesn't require the value of the allocator was the one passed in.
STL: After looking at this, I think I'm comfortable with the edits. The previous Standardese was nonsense so it's pretty easy to improve upon.
Marshall: Any other opinions?
Marshall: Any objections to moving it to Ready? Review? Ready in Kona?
Wakely: My preference would be Ready. We all know this is what we're doing anyways.
Nevin: The intent won't change.
STL: I think this is the right fix.
Hwrd: I third Ready. Even if Jonathan retracts his.
Marshall: Ready!

Proposed resolution:

This wording is relative to N3485.

1. Edit 24.2.2.1 [container.requirements.general] paragraph 3:

   > For the components affected by this subclause that declare an `allocator_type`, objects stored in these components shall be constructed using the `allocator_traits<allocator_type>::rebind_traits<U>::construct` function and destroyed using the `allocator_traits<allocator_type>::rebind_traits<U>::destroy` function (20.2.9.3 [allocator.traits.members]), where `U` is either `allocator_type::value_type` or an internal type used by the container. These functions are called only for the container's element type, not for internal types used by the container. [ Note: This means, for example, that a node-based container might need to construct nodes containing aligned buffers and call construct to place the element into the buffer. — end note ]

2. Edit 24.2.2.1 [container.requirements.general] paragraph 7:

   > […] A copy of this allocator is used for any memory allocation and element construction performed, by these constructors and by all member functions, during the lifetime of each container object or until the allocator is replaced. […]

3. Edit 24.2.2.1 [container.requirements.general] paragraph 13:

   > […] Given an allocator type `A` and given a container type `X` having an `allocator_type` identical to `A` and a `value_type` identical to `T` and an `allocator_type` identical to `allocator_traits<A>::rebind_alloc<T>` and given an lvalue `m` of type `A`, a pointer `p` of type `T*`, an expression `v` of type (possibly `const`) `T`, and an rvalue `rv` of type `T`, the following terms are defined.

   > […]

   > [ Note: A container calls `allocator_traits<A>::construct(m, p, args)` to construct an element at `p` using `args`, with `m == get_allocator()`. The default `construct` in `std::allocator` will call `::new((void*)p) T(args)`, but specialized allocators may choose a different definition. — end note ]