This is the mail archive of the
mailing list for the libstdc++ project.
std::vector allocator-extended move constructor
- From: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- To: "libstdc++" <libstdc++ at gcc dot gnu dot org>
- Date: Fri, 15 Nov 2013 12:11:52 +0000
- Subject: std::vector allocator-extended move constructor
- Authentication-results: sourceware.org; auth=none
I'm finishing allocator support for <map> and <set> and noticed a
problem in std::vector:
/// Move constructor with alternative allocator
vector(vector&& __rv, const allocator_type& __m)
: _Base(std::move(__rv), __m)
if (__rv.get_allocator() != __m)
The good news is that if all instances of the allocator type compare
equal then the _Base will just move some pointers, so we can have a
The bad news is that it's not currently exception-safe. I should have
used __uninitialized_copy_a there. If moving any element throws an
exception then we leak any already-moved elements.
We could try to conditionally use moves, but we can't just check for
is_nothrow_move_constructible, because the allocator can call a
different constructor, e.g. scoped allocators will call an
allocator-extended move constructor. So we would need a new trait
"is_nothrow_move_insertable", which would depend on
std::declval<_Tp>())) but that will only give the right answer if we
add a conditional noexcept on std::allocator_traits<A>::construct(),
and that will only give the right answer if A::construct() has a
conditional noexcept on its construct() member function (or there is
no viable A::construct().) It might be worth doing all that and
adding conditional noexcept on std::allocator::construct() in the
future, but for now I'm just going to switch to using
__uninitialized_copy_a() to be safe.
Can anyone see any flaws in my analysis before I make that change?