I naively expected this program to compile and run with a success status:
#include <iterator>
#include <string>
int main()
{
const std::string s = "foo";
auto forward_iter = s.begin();
auto reverse_iter = std::make_reverse_iterator(forward_iter);
auto third_iter = std::make_reverse_iterator(reverse_iter);
return forward_iter != third_iter;
}
It fails to compile, because the type of third_iter
isn't the same as that of the forward_iter
we started with; instead it's a reverse_iterator<reverse_iterator<normal_iterator>>
:
0.cpp:10:25: error: no match for ‘operator!=’ (operand types are ‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >’ and ‘std::reverse_iterator<std::reverse_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > > >’)
return forward_iter != third_iter;
~~~~~~~~~~~~~^~~~~~~~~~~~~
Re-reading the documentation, it appears that std::make_reverse_iterator(it)
is specified to always wrap it
, even if it
is already a reverse iterator (and to some extent that makes sense, because we'll be expecting to use reverse_iterator
members (i.e. base()
).
Is there a standard way to swap between normal (forward) and wrapped (reverse) iterators, without knowing which type I have? Or do I need to write a SFINAE pair of functions to return std::make_reverse_iterator(it)
and it.base()
appropriately?
No. Or at least, that's not how
make_reverse_iterator
has been specified. The return type is specified to bereverse_iterator<Iterator>
in the standard.No. Not as far as I know.
You can write it. I can't say whether you need it.
Here's one implementation:
And a test: