我在使用gcc的非const容器上使用const反向迭代器时遇到问题。好吧,只有某些版本的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;
}
这个程序编译好并运行gcc 4.2.1(Mac Leopard)和Visual Studio 8和9(Windows)以及gcc 4.1.2(Linux)。
但是,gcc 3.4.4(cygwin)和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>]()'
这是早期版本的gcc中的错误吗?
由于Mac上的gcc 4.2.1存在其他问题,我们需要在Mac上使用gcc 4.0.1,因此只使用较新的编译器对我来说不是一个完美的解决方案。所以我想我需要改变我使用反向迭代器的方式。有什么建议吗?
答案 0 :(得分:10)
这是当前标准中的一个缺陷:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#280
修改:详细说明: 问题是,在现行标准中:
vector::reverse_iterator
指定为std::reverse_iterator<vector::iterator>
,vector::const_reverse_iterator
指定为std::reverse_iterator<vector::const_iterator>
。std::reverse_iterator
上的关系运算符使用单个模板参数定义,使reverse_iterator<iterator>
和reverse_iterator<const_iterator>
不具有可比性。在你的代码中,你将const_reverse_iterator
与非常量向量上调用“rend()”的结果进行比较,这是一个(非常量)reverse_iterator
。
在C ++ 0x中,进行了两项相关更改以修复如下问题:
在您的情况下,解决方法是明确请求const_reverse_iterator为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;
答案 1 :(得分:2)
我会尝试随机的事情:
将rend()的返回值转换为const_reverse_iterator,以查看问题是在比较常规迭代器还是常量迭代器:
r != static_cast<vector<char>::const_reverse_iterator>(v.rend())
如果这不起作用,如何将r从const_reverse_iterator更改为常规反向迭代器。
如果这些工作没有任何线索,但这就是我在这种情况下尝试的。
答案 2 :(得分:2)
由于迭代器需要是可比较的相同类型,并且非const容器产生非const迭代器,为什么不同时声明和初始化结束迭代器。
for (vector<char>::const_reverse_iterator r = v.rbegin(), end_it = v.rend(); r != end_it; ++r)
cout << *r;
使用较旧的编译器,这甚至可以带来很小的性能优势。
答案 3 :(得分:1)
可能是gcc旧版本中的一个错误,但我的猜测是错误存在于您的代码中 - 您未能#include <iterator>
。如果修复不能解决问题,那么可能只值得进一步研究。
另一方面,如果您使用的是显示的reverse_iterator
(即循环体是cout << *r;
),您应该只使用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);
还有一个copy_backwards
,但我不相信它会做你想要的。
编辑:另一种可能需要考虑的方法:如果添加所需的标头不起作用,并且您确实需要反向迭代器,则可以考虑使用STLPort代替本机库(至少对于较旧的库)编译器)。