gcc reverse_iterator比较运算符丢失了吗?

时间:2010-01-25 19:45:09

标签: c++ gcc stl iterator

我在使用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,因此只使用较新的编译器对我来说不是一个完美的解决方案。所以我想我需要改变我使用反向迭代器的方式。有什么建议吗?

4 个答案:

答案 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中,进行了两项相关更改以修复如下问题:

  • reverse_iterator上的关系运算符现在采用两个模板参数
  • 像vector这样的容器有额外的方法来明确地请求一个const_iterator:cbegin(),cend(),crbegin()和crend()。

在您的情况下,解决方法是明确请求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代替本机库(至少对于较旧的库)编译器)。