destroy
and fancy pointer operations must be non-throwingSection: 16.4.4.6 [allocator.requirements] Status: New Submitter: Billy O'Neal III Opened: 2018-09-07 Last modified: 2018-12-16
Priority: 3
View other active issues in [allocator.requirements].
View all other issues in [allocator.requirements].
View all issues with New status.
Discussion:
In annotating things required to be called by ~vector
, Casey pointed out that several operations I guarded
with noexcept
aren't actually mandated by the standard to be noexcept
. However, the STL, and more
specifically here, containers, consider inability to destroy an element an unrecoverable condition. This is evidenced
for the whole STL by 16.4.6.13 [res.on.exception.handling]/3 "Every destructor in the C ++ standard library shall
behave as if it had a non-throwing exception specification.".
allocator::destroy
and fancy pointer operations must be non-throwing for valid input, or the
containers don't make any sense. This is obvious for things like vector::~vector
, but less obviously the
containers rely on these guarantees whenever inserting more than one element, etc.
Moreover, we too narrowly specify the domain of the pointer_traits::pointer_to
requirement in the
Cpp17Allocator
requirements, because any node-based container that uses container-internal sentinel
nodes needs to be able to form pointers to said sentinel nodes; that operation must also be non-throwing.
[2018-09 Reflector prioritization]
Set Priority to 3
Proposed resolution:
This wording is relative to N4762.
Modify 16.4.4.6 [allocator.requirements], Table 32 "Descriptive variable definitions" as indicated:
Table 32 — Descriptive variable definitions Variable Definition …
YY
the type allocator_traits<Y>
Z
an allocator-aware container type (23.2.2 [container.requirements.general]) …
y
a value of type XX::const_void_pointer
obtained by
conversion from a result value ofYY::allocate
, or else a
value of type (possiblyconst
)std::nullptr_t
.z
an lvalue of type Z
such thatz.get_allocator() == a
r1
a reference to any member subobject of z
n
a value of type XX::size_type
.…
Modify 16.4.4.6 [allocator.requirements], Table 33 "Cpp17Allocator
requirements" as indicated:
Table 33 — Cpp17Allocator
requirementsExpression Return type Assertion/note
pre-/post-conditionDefault …
pointer_traits<
X::pointer
>::pointer_to(r)X::pointer
S same asp
.
Throws: Nothing.pointer_traits<
X::pointer
>::pointer_to(r1)A value of type YY::pointer
or
YY::const_pointer
k
such that
*k
isr1
.
Throws: Nothing.…
a.destroy(c)
(not used) Effects: Destroys the object at c
.
Throws: Nothing.c->~C()
…
Modify 16.4.4.6 [allocator.requirements], p5, as indicated:
-5- An allocator type
X
shall satisfy theCpp17CopyConstructible
requirements (Table 26). TheX::pointer
,X::const_pointer
,X::void_pointer
, andX::const_void_pointer
types shall satisfy theCpp17NullablePointer
requirements (Table 30). No constructor, comparison function, copy operation, move operation, or swap operation on these pointer types shall exit via an exception.X::pointer
andX::const_pointer
shall also satisfy the requirements for a random access iterator (24.3.5.7 [random.access.iterators]) and of a contiguous iterator (24.3.1 [iterator.requirements.general]) and operations in those requirements shall not exit via an exception so long as resulting iterators are dereferencable or past-the-end.
Modify 20.2.9.3 [allocator.traits.members], as indicated:
template<class T> static void destroy(Alloc& a, T* p);-6- Effects: Calls
-?- Throws: Nothing.a.destroy(p)
if that call is well-formed; otherwise, invokesp->~T()
.