I am having a problem using const reverse iterators on non-const containers with gcc. Well, only certain versions of gcc.
#include <vector>
#include <iostream>
using namespace std;
int main() {
const char v0[4] = "abc";
vector<char> v(v0, v0 + 3);
// This block works fine
vector<char>::const_iterator i;
for (i = v.begin(); i != v.end(); ++i)
cout << *i;
cout << endl;
// This block generates compile error with gcc 3.4.4 and gcc 4.0.1
vector<char>::const_reverse_iterator r;
for (r = v.rbegin(); r != v.rend(); ++r)
cout << *r;
cout << endl;
return 0;
}
This program compiles OK and runs with gcc 4.2.1 (Mac Leopard) and with Visual Studio 8 and 9 (Windows), and with gcc 4.1.2 (Linux).
However, there is a compile error with gcc 3.4.4 (cygwin) and with gcc 4.0.1 (Mac Snow Leopard).
test.cpp:18: error: no match for 'operator!=' in 'r != std::vector<_Tp, _Alloc>::rend() [with _Tp = char, _Alloc = std::allocator<char>]()'
Is this a bug in earlier versions of gcc?
Due to other problems with gcc 4.2.1 on Mac, we need to use gcc 4.0.1 on Mac, so simply using the newer compiler is not a perfect solution for me. So I guess I need to change how I use reverse iterators. Any suggestions?
It is a defect in the current standard: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#280
Edit : Elaborating a bit: The issue is that, in the current standard:
vector::reverse_iterator
is specified as std::reverse_iterator<vector::iterator>
, and vector::const_reverse_iterator
as std::reverse_iterator<vector::const_iterator>
. std::reverse_iterator
are defined with a single template parameter, making reverse_iterator<iterator>
and reverse_iterator<const_iterator>
non-comparable. In your code, you compare a const_reverse_iterator
with the result of calling "rend()" on a non-const vector, which is a (non-const) reverse_iterator
.
In C++0x, two related changes are made to fix issues like this:
In your case, a workaround would be to explicitely request the const_reverse_iterator for rend():
vector<char>::const_reverse_iterator r;
const vector<char>::const_reverse_iterator crend = v.rend();
for (r = v.rbegin(); r != crend; ++r)
cout << *r;
Random things I would try:
Cast the return from rend() to a const_reverse_iterator to see if the issue is in comparing a regular to a const iterator:
r != static_cast<vector<char>::const_reverse_iterator>(v.rend())
If that doesn't work, how about changing r from a const_reverse_iterator to a regular reverse iterator.
No clue if these work, but that's what I'd try in this situation.
Since the iterators need to be the same type to be comparable, and a non-const container yields non-const iterators, why not declare and initialize the end iterator at the same time.
for (vector<char>::const_reverse_iterator r = v.rbegin(), end_it = v.rend(); r != end_it; ++r)
cout << *r;
With an older compiler this might even give a small performance benefit.
It could be a bug in the old vesion of gcc, but my guess is that the bug is in your code -- you've failed to #include <iterator>
. It's probably only worth looking further if fixing that doesn't fix the problem.
On the other hand, if you're using the reverse_iterator
as shown (ie the body of the loop is cout << *r;
) you should probably just use std::copy
:
std::ostream_iterator<char> output(std::cout);
// frontwards
std::copy(v.begin(), v.end(), output);
// backwards
std::copy(v.rbegin(), v.rend(), output);
There is also a copy_backwards
, but I don't believe it'll do what you want.
Edit: One other possibility to consider: if adding the required header doesn't work, and you really need the reverse iterator, you might consider using STLPort in place of the native library (at least for the older compilers).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.