检查迭代器是否属于列表 有没有一种方法可以检查C++中给定迭代器是否属于给定列表?明显但无效的方法

检查迭代器是否属于列表 有没有一种方法可以检查C++中给定迭代器是否属于给定列表?明显但无效的方法,c++,stl,C++,Stl,您不能简单地遍历列表,将每个迭代器值与您的“候选者”进行比较 C++03标准对应用于不同容器的迭代器的=的有效性含糊不清(Mankarse对Nawaz的答案链接的评论),一些编译器(例如VC++2005调试模式)警告如果您这样做,但是,尽管它实际上可以根据编译器/库可靠地工作,如果您不关心可移植性,请查看它的文档 C++11标准非常明确,您不能将迭代器与不同的容器进行比较: §24.2.5正向迭代器的==域是相同基础序列上迭代器的域 因此,这个问题的答案依赖于操作符==,现在是有问题的,将来也是

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

C++03标准对应用于不同容器的迭代器的
=
的有效性含糊不清(Mankarse对Nawaz的答案链接的评论),一些编译器(例如VC++2005调试模式)警告如果您这样做,但是,尽管它实际上可以根据编译器/库可靠地工作,如果您不关心可移植性,请查看它的文档

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

§24.2.5正向迭代器的==域是相同基础序列上迭代器的域

因此,这个问题的答案依赖于
操作符==
,现在是有问题的,将来也是无效的

经常有效的方法 您可以做的是沿着列表进行迭代,将元素的地址(即,
&*i
)与其他迭代指向的对象的地址进行比较

  • Mankarse的评论警告说,对于提供自己的
    操作符的对象&
    ,这可能无法正常工作。您可以使用或针对C++03解决此问题

  • 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;
}
模板
内联布尔范围包含(迭代器从、常量迭代器和结束、,
常量迭代器(可选)
{
while(from!=结束)
如果(&*from++=&*candidate)
返回true;
返回false;
}
注:

  • 这采用了标准的库方法,即接受一系列迭代器位置进行搜索
  • 每个迭代器的类型允许不同,因为存在可移植性问题,例如,
    begin()
    返回一个
    iterator
    end()
    返回一个
    const\u迭代器的容器
  • 中的
    之外的迭代器由
    常量
    引用获取,因为迭代器有时可能是非平凡对象(即,太大而无法放入寄存器,复制成本相对较高)<值需要code>from
    ,因为它将在整个范围内递增

@托尼:谢谢你对我的回答发表评论,这是大错特错。我只是不得不删除它。吸取的教训:一心多用是不好的,尤其是在工作和生活中玩杂耍!请注意,这仍然只适用于ForwardIterator(及其改进),因此在一般情况下需要小心。@Als:我非常惊讶,因为我已经看到了您的许多其他答案,并且知道它们通常是多么完美。我经常被同样的方式卡住。。。别担心。。。。比较元素的地址…——当然,如果传递的迭代器恰好指向空列表的
end()
(或
begin()
),则再次取消对它的引用。真是一团糟!:-)@托尼:我认为这是一个合理的先决条件。使用
end
迭代器(属于InputIterator类别)唯一有效的方法是使用
==
将其与同一容器中的另一个迭代器进行比较=。因此,除非调用方还告诉您迭代器来自哪个容器,否则您必须对迭代器提出一些要求以避免这种情况。