检查迭代器是否属于列表

Pau*_*nta 16 c++ stl

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

Ton*_*roy 19

明显但无效的方法

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

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

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

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

所以,依赖的这个问题的答案operator==现在是有问题的,将来也是无效的.

一种经常有效的方法

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

  • Mankarse的评论警告说,这可能不适用于提供自己的对象operator&.您可以使用std::addressof或使用C++ 03 boost版本来解决此问题

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

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

执行:

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;
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 这采用标准库方法接受一系列迭代器位置进行搜索.
  • 该类型的每个迭代器都允许变化,因为有可移植性问题,其中如集装箱begin()返回iterator,但end()返回const_iterator.
  • 比其他迭代from采取通过const引用,如迭代器有时是不平凡的对象(即过大而无法在寄存器中,相对昂贵的复制). from值需要它,因为它将在范围内递增.