9

如果我有范围(一对 2 个迭代器),有没有办法为使用范围而不是原始数组或容器编写“for each”循环。

像这样的东西:

auto rng = std::equal_range(v.begin(),v.end(),1984);
for(const auto& elem: rng) {
    // ...
}
4

4 回答 4

14

根据为什么从 C++11 中删除了对范围访问?您可以使用适配器,例如as_rangeat 接受的答案boost::make_iterator_range,或编写您自己的:

template<typename It> struct range {
   It begin_, end_;
   It begin() const { return begin_; }
   It end() const { return end_; }
};
template<typename It> range<It> as_range(const std::pair<It, It> &p) {
   return {p.first, p.second};
}

auto rng = std::equal_range(v.begin(),v.end(),1984);
for(const auto& elem: as_range(rng))
    ...

这通常不适用的原因是,根据Alastair Meredith 的论文,算法,

  • mismatchpartition_copy返回一对来自不同范围的迭代器;
  • minmax返回一对可能根本不是迭代器的对象,如果它们是,则不能保证它们形成一个范围;
  • minmax_element可以返回一个范围,但它也可以返回一个反向范围(例如,在反向排序的范围minmax_element上将返回{prev(last), first};
  • equal_range保证返回一个范围。
于 2013-03-20T17:21:20.290 回答
3

我不认为它会像返回一对迭代器一样开箱即用地工作equal_range,而根据文档的 for 循环范围是:

The begin_expr and end_expr are defined to be either:
If (__range) is an array, then (__range) and (__range + __bound), where __bound is the array bound
If (__range) is a class and has either a begin or end member (or both), then begin_expr is __range.begin() and end_expr is __range.end();
Otherwise, begin(__range) and end(__range), which are found based on argument-dependent lookup rules with std as an associated namespace.

我想说你可以定义beginend函数来接受这对迭代器并分别返回第一个和第二个。

于 2013-03-20T17:18:41.307 回答
1
#include <vector>
#include <algorithm>
#include <iostream>

template <typename I>
struct range_adapter {
    std::pair<I, I> p;

    range_adapter(const std::pair<I, I> &p) : p(p) {}

    I begin() const { return p.first; }
    I end() const { return p.second; }
};

template <typename I>
range_adapter<I> in_range(const std::pair<I, I> &p)
{
    return range_adapter<I>(p);
}

int main()
{
    std::vector<int> data { 1, 2, 2, 3, 3, 3, 4 };

    auto r = std::equal_range(data.begin(), data.end(), 2);

    for (const auto &elem : in_range(r))
    {
        std::cout << elem << std::endl;
    }
}
于 2013-03-20T17:24:29.863 回答
0

std::equal_range返回的只是一个 std::pair 。该标准不涵盖任何迭代此类事物的方法。

您可能想阅读的是 Alexandrescu 的“Iterators must go”演示文稿。这是视频。关于使用 Ranges 迭代容器的更优雅方式的优秀读物。

范围在他的Loki库中实现。

于 2013-03-20T17:22:23.637 回答