c++movervalue

Why are there no rvalue ref-qualified begin() overloads in STL containers?


In the following code:

#include <vector>
int main() {
  using vec_t = std::vector<int>;
  vec_t v;
  auto it1{std::move(v).begin()};// type is vec_t::iterator
  auto it2{std::make_move_iterator(v.begin())}; // type is std::move_iterator<__gnu_cxx::__normal_iterator<int *, vec_t::iterator>>
}

the variable it1 has type vec_t::iterator even though begin() is called on the r-value std::move(v), which would seem natural to me. I am wondering why it does not return a move_iterator. Why is there no rvalue ref-qualified overload of begin()? What is the logic behind this?


Solution

  • There would barely be a consistent use case for begin() && and end() &&.

    When a function's parameter is declared as

    void foo(std::vector<int>&& vec)
    

    then vec is an lvalue at this point and these versions of begin and end would not be picked up anyway.

    But if you later say

        std::for_each(std::move(vec).begin(), std::move(vec).end(), ...);
    

    you have basically given away vec twice. That is against any convention and programming guideline.

    On the other hand,

        std::for_each(std::make_move_iterator(vec.begin()), std::make_move_iterator(vec.end()), ...);
    

    makes the intent very clear.