move_iterator is broken for iterators returning prvalues and returns dangling reference

c++, c++11, iterator, move-semantics, stl

Solution

The problem you are experiencing is known to the C++ committee. This problem is being tracked by LWG issue 2106. This issue is currently in Open status, meaning the resolution has not yet been decided upon.

Update

LWG issue 2106 was accepted in time for C++17. The PR is at the bottom of the issue (link corrected in this update).

Problem

I've looked in the STL sources for `std::move_iterator<Iterator>` and found out that it returns `Iterator::value_type&&`. This leads to incorrect behaviour when `Iterator::reference` is an rvalue and not the same as `Iterator::value_type&`. I have a class with a proxy object as `reference` (like in `std::vector<bool>`), which can implicitly cast to `value_type`. The normal iterator just dereferences to this proxy (the input iterator requirements allow this), but `std::move_iterator` invokes casting to `value_type` with an overhead and then returns a dangling reference to the created temporary object. `std::move_iterator` still works with `std::vector<bool>` for some reason (probably because bool is a simple type, and a dangling `bool&&` doesn't cause an error), but not with my class. It's confusing me and I don't understand how to fix it, I think it's a bug in STL. Here is the simplified piece of source for `std::move_iterator` from GCC 4.8.1: ``` template <typename Iterator> class move_iterator { public: typedef typename iterator_traits<Iterator>::value_type value_type; typedef value_type&& reference; reference operator*() const { return std::move(*it); } private: Iterator it; }; ```

Original source