139

In the process of answering another question I stumbled upon slightly different wordings for std::vector::erase() and std::deque::erase().

This is what C++14 says about std::deque::erase ([deque.modifiers]/4-6, emphasis mine):

Effects: ...

Complexity: The number of calls to the destructor is the same as the number of elements erased, but The number of calls to the assignment operator is no more than the lesser of the number of elements Before the erased elements and the number of elements after the erased elements.

Throws: Nothing unless an exception is thrown by the copy constructor, move constructor, assignment operator, or move assignment operator of T.

And here is what it says about std::vector::erase ([vector.modifiers]/3-5):

Effects: ...

Complexity: The destructor of T is called the number of times equal to the number of the elements erased, but the move assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements.

Throws: Nothing unless an exception is thrown by the copy constructor, move constructor, assignment operator, or move assignment operator of T.

As you can see, the exception specifications for both of them are the same, but for std::vector it's explicitly mentioned that move assignment operator is called.

There's also requirement for T to be MoveAssignable for erase() to work with both std::vector and std::deque (Table 100), but this doesn't imply the presence of the move assignment operator: one can define a copy assignment operator, and not define move assignment operator, and this class will be MoveAssignable.

Just in case, I checked with GCC and Clang, and indeed std::vector::erase() calls copy assignment operator if there's no move assignment operator, and std::deque::erase() does the same (DEMO).

So the question is: did I miss something, or this is an (editorial) issue in the standard?

Update: I've submitted an LWG issue #2477.

Community
  • 1
  • 1
Anton Savin
  • 40,838
  • 8
  • 54
  • 90
  • 14
    Seems like a defect in the standard. – Barry Feb 02 '15 at 13:33
  • 4
    ^ ack. An LWG-issue would be appropriate. – Columbo Feb 05 '15 at 14:52
  • 4
    Usually the draft standard is good enough. This is one of those cases where you should be looking at the real thing. – Mark Ransom Feb 26 '15 at 15:46
  • 3
    @MarkRansom the current source of the standard for [std::deque](https://github.com/cplusplus/draft/blob/master/source/containers.tex#L3185) and [std::vector](https://github.com/cplusplus/draft/blob/master/source/containers.tex#L5095) is the same as in the question, so the probability that the final version differs is very little. – Anton Savin Feb 28 '15 at 20:11
  • 3
    N4141 has the same wording as N4140. – Brian Bi Apr 09 '15 at 22:44
  • Isn't move assignement operator a more specialized assignment operator ? I don't see any conflict from the code example with the behavior described. – xryl669 May 12 '15 at 12:46
  • @xryl669 I'm pretty he's asking why there is a difference. Why is it more specific in one situation than the other? – CinchBlue May 14 '15 at 10:09
  • As the LWG issue has now been resolved, you could post an answer with the changes made... –  May 14 '15 at 16:13

1 Answers1

10

At Lenexa meeting the issue got Immediate status with proposed resolution:

This wording is relative to N4296.

Change 23.3.3.4 [deque.modifiers]/5 to:

-5- Complexity: The number of calls to the destructor of T is the same as the number of elements erased, but the number of calls to the assignment operator of T is no more than the lesser of the number of elements before the erased elements and the number of elements after the erased elements.

Change 23.3.6.5 [vector.modifiers]/4 to:

-4- Complexity: The destructor of T is called the number of times equal to the number of the elements erased, but the move assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements.

That is, if the resolution is accepted there will be no special mention of the move assignment for std::vector::erase, and also the wording for std::deque::erase will be clarified a bit.

Community
  • 1
  • 1
Anton Savin
  • 40,838
  • 8
  • 54
  • 90