重载运算符<对于非随机迭代器

时间:2015-10-23 15:06:13

标签: c++ list operator-overloading

我想知道我们是否可以为非随机operator <重载iterators,例如std::liststd::map等。例如,如果我重载它对于std::list然后:

bool operator < (std::list<T>::iterator &i1, std::list<T>::iterator &i2)
{
    return (&*i1 < &*i2);
}

我的主要目的是进行这样的迭代:

for (auto i = l.begin(); i < l.end(); ++i) // possible for std::vector, std::deque, etc
// I want to do this instead of i != l.end()

但是编译器说:

  

[错误]声明operator<为非功能

任何人都有解决方案吗?

3 个答案:

答案 0 :(得分:3)

你的工作方向错误。由于某种原因,非随机访问迭代器不支持operation <。基本上,不可能以合理的方式为非随机访问迭代器实现operation <。在你的情况下,你应该写:

for (auto i = l.begin(); i != l.end(); ++i)

代替。或者,如果支持C ++ 11,请考虑使用基于范围的for循环的可能性。

关于你的代码:

bool operator < (std::list<T>::iterator &i1, std::list<T>::iterator &i2)
{
    return (&*i1 < &*i2);
}

两种方式都不行。

  1. std::list<T>::iterator是一个从属名称。您需要使用typename
  2. 对其进行限定
  3. 无法从迭代器类型推导出T的模板参数。必须明确指定。
  4. 那么,如何解决第二个问题呢?好吧,我认为不可能。迭代器的实际类型未在标准中指定,并被视为实现细节。

答案 1 :(得分:3)

对不提供它的迭代器进行小于比较是没有意义的。使用带有std::list的示例,列表中的节点可以位于内存中的任何位置。尝试比较节点的地址是没有意义的,因为第一个节点可能具有比所有其他节点更高的地址。如果是这种情况,那么你永远不会遍历列表。这种方法的唯一方法是使用一个标记节点(end)并进行每次迭代检查以确定是否与它不相等。通过这样做,你知道你没有达到目的,你可以继续。一旦你比较等于end,你知道你已经到达列表的末尾。

答案 2 :(得分:1)

我建议使用std::remove_if(然后当然是erase),这更清楚你正在做什么,也应该是有效的。如果你可以使用C ++ 11那么谓词可以是一个lambda,而且它非常紧凑。