The program is guaranteed to work according to the standard.
std::unique requires an iterator. The easiest way to show that moving iterators satisfy this requirement is to check the iterator_category typedef move_iterator :
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
As you can see, the iterator category of the base type of the iterator directly adapts. In fact, the behavior of displacement iterators is almost equivalent to their main ones, [move.iterators] / 1:
The class template move_iterator is an iterator adapter with the same behavior as the main iterator, except that its indirectness operator implicitly converts the value returned by the base iterator to the rvalue help system.
There are no other notable requirements: It is clear that vector<>::iterator is an input iterator (as required [move.iter.requirements]). The only relevant requirement imposed by unique itself is
The *first type must satisfy the requirements of MoveAssignable (Table 22).
... which directly meets.
Note that using move iterators should not bring any advantages over normal ones. Internally duplicate elements are assigned along the way (hence the MoveAssignable requirement), so returning an rvalue link from operator* is unnecessary.
source share