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.
allocator_traits::construct()
Section: 23.2.2 [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, 23.2.2 [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, 23.2.2 [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
23.2.2 [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.
[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>::
"
[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.
Edit 23.2.2 [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 theallocator_traits<allocator_type>::rebind_traits<U>::construct
function and destroyed using theallocator_traits<allocator_type>::rebind_traits<U>::destroy
function (20.2.9.3 [allocator.traits.members]), whereU
is eitherallocator_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 ]
Edit 23.2.2 [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. […]
Edit 23.2.2 [container.requirements.general] paragraph 13:
[…] Given an allocator type
[…] [ Note: A container callsA
and given a container typeX
havinganaallocator_type
identical toA
andvalue_type
identical toT
and anallocator_type
identical toallocator_traits<A>::rebind_alloc<T>
and given an lvaluem
of typeA
, a pointerp
of typeT*
, an expressionv
of type (possiblyconst
)T
, and an rvaluerv
of typeT
, the following terms are defined.allocator_traits<A>::construct(m, p, args)
to construct an element atp
usingargs
, withm == get_allocator()
. The defaultconstruct
instd::allocator
will call::new((void*)p) T(args)
, but specialized allocators may choose a different definition. — end note ]