Opened 5 years ago

Closed 5 years ago

#13420 closed Bugs (invalid)

small_vector - invalid move constructor/move assignment for size < N

Reported by: Antervis Owned by: Ion Gaztañaga
Milestone: To Be Determined Component: container
Version: Boost 1.66.0 Severity: Problem
Keywords: small_vector, move Cc: Russkov.AD@…

Description

When small_vector is move-constructed or move-assigned from another small_vector, the initial one has elements moved out, but vector size is left unchanged. This only happens if internal vector memory is used (vector size is less than in-place capacity N)

small_vector<int, 5> a = {1,2,3};
small_vector<int, 5> b = std::move(a);
// after the assignment, a.size() is 3

Detailed example is here.

Change History (4)

comment:1 by anonymous, 5 years ago

Version: Boost 1.65.0Boost 1.66.0

comment:2 by Ion Gaztañaga, 5 years ago

There is not requirement that a move constructor or assignment must empty the source. Source must be in a consistent but unspecified state.

in reply to:  2 comment:3 by Antervis, 5 years ago

Replying to Ion Gaztañaga:

There is not requirement that a move constructor or assignment must empty the source. Source must be in a consistent but unspecified state.

even though current behavior is standard-conforming, it is certainly inconsistent both with standard containers (which are empty after being moved out) and with itself (moved out state depends on initial state). I personally don't see a reason for this behavior to be an intended design choice and I suggest it to be changed

comment:4 by Ion Gaztañaga, 5 years ago

Resolution: invalid
Status: newclosed

I've reviewed some STL implementations, specifically operator=(vector&&source), the case when the allocator shall not be propagated allocator_traits::propagate_on_container_move_assignment or allocators don't compare equal. In those cases memory can't be stolen from the source container and elements are move constructed from source to destination.

  • libstdc++ clears the source vector
  • libc++ and msvc don't clear the source vector (size is unchanged)

The standard says for operator=(vector&&) (the move constructor always transfers the allocator and does not support different storage types for source and destination like small_vector) that *this shall have the same value "source" had but no guarantee about the state of "source".

So I'm reluctant to change the implementation to clear the source. If many users find this annoying then we will reopen the issue. Thanks for the report.

Note: See TracTickets for help on using tickets.