C++98 containers defined two kinds of iterator, ::iterator
s and ::const_iterators
. Generally, like this:
struct vec{
iterator begin() ;
const_iterator begin() const;
};
In C++11 this part of the design seems to be unchanged.
The question is,
for consistency and for practical purposes would it make sense to add ::move_iterator
s as well? or it an overkill.
I can imagine that an rvalue container maybe have their elements moved if possible.
class vec{
iterator begin() &;
const_iterator begin() const&;
move_iterator begin() &&;
};
If I understand correctly, it could be implemented like this in simple cases:
auto vec::begin() &&{return std::make_move_iterator(this->begin());}
Of course a normal iterator can be converted to a move iterator (with std::make_move_iterator
), however the motivations is generic code.
For example, with a move iterator this would be very elegantly implemented without conditions depending on whether the argument is an lvalue or an rvalue.
template<class Container, class T = Container::value_type>
void transport_first(Container&& c, std::vector<T>& v){
v.emplace_back(*std::forward<Container>(c).begin());
}
Note that this code would incur in no unnecessary copies if possible.
How can this be implemented without move_iterators
generated by begin
.
I also realize that this question applies to almost any accessor to the container, for example, operator[]
, front()
and back()
.
template<class Value>
class vec{
using value_type = Value;
using reference = Value&;
using const_reference = Value const&;
using rvalue_reference = Value&&; // NEW!
reference front() &{...}
rvalue_reference front() &&{...} // NEW!
const_reference front() const&{...}
};
Perhaps containers should have been redesigned from scratch in C++11. Their design is showing its age.
There is a proposal, to automatically deduce the (decl)type of (*this)
basically having all the corresponding overload of begin (and other member functions) for free.