This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

std::vector allocator-extended move constructor


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)
      {
        this->_M_impl._M_finish =
          std::__uninitialized_move_a(__rv.begin(), __rv.end(),
                      this->_M_impl._M_start,
                      _M_get_Tp_allocator());
        __rv.clear();
      }
  }

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
conditional noexcept:
      noexcept(_Alloc_traits::_S_always_equal())

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
noexcept(_Alloc_traits::construct(_M_get_Tp_allocator(),
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?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]