检查迭代器是否属于列表

时间:2011-06-10 06:26:16

标签: c++ stl

有没有办法检查给定的迭代器是否属于C ++中的给定列表?

1 个答案:

答案 0 :(得分:18)

明显但无效的方法

您不能简单地遍历列表,将每个迭代器值与“候选者”进行比较。

C ++ 03标准对于应用于来自不同容器的迭代器的==的有效性(Mankarse对Nawaz的答案链接http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2948.html#446的评论),一些编译器(例如VC ++ 2005 debug)的含义模糊不清模式)警告你是否这样做,但尽管它可能实际上可靠地工作取决于你的编译器/库 - 如果你不关心可移植性,请检查它的文档。

C ++ 11标准非常明确,您无法将迭代器与不同容器进行比较

  

§24.2.5前向迭代器的==域是同一基础序列上的迭代器的域。

因此,依赖于operator==的此问题的答案现在有问题,将来无效。

一种经常有效的方法

可以做的是沿着列表迭代,将元素的地址(即&*i)与你的另一个迭代所指向的对象的地址进行比较。

  • Mankarse的评论警告说,这可能不适用于提供自己operator&的对象。您可以使用std::addressof或C ++ 03 boost's version

  • 解决此问题
  • Martin的评论提到你必须假设你正在测试列表成员资格的候选迭代器是安全可解除引用的 - 即不等于它所来自的容器上的end()迭代器。史蒂夫指出 - 这是一个非常合理的前提条件,不应该让任何人感到惊讶。

(这适用于所有标准容器,因为存储的元素永远不会具有相同的地址,但更通常用户定义的容器可能允许不相等的迭代器处理相同的值对象(例如支持循环或“flyweight模式”样式)优化),在这种情况下这种方法会失败。但是,如果你编写这样一个容器,你可能会设计安全的迭代器比较。)

实现:

template <class IteratorA, class IteratorB, class IteratorC>
inline bool range_contains(IteratorA from, const IteratorB& end,
                           const IteratorC& candidate)
{
    while (from != end)
        if (&*from++ == &*candidate)
            return true;
    return false;
}

注意:

  • 这采用标准库方法接受一系列迭代器位置进行搜索。
  • 允许每个迭代器的类型变化,因为存在可移植性问题,例如容器begin()返回iteratorend()返回const_iterator
  • from以外的迭代器由const引用获取,因为迭代器有时可能是非平凡的对象(即,太大而无法放入寄存器,复制起来相对昂贵)。值需要from,因为它将在范围内递增。