可以基于范围的循环工作范围

时间:2013-03-20 17:13:25

标签: c++ c++11 foreach

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

这样的事情:

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

4 个答案:

答案 0 :(得分:14)

根据Why was pair range access removed from C++11?,您可以使用适配器,例如接受回答的as_rangeboost::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's paper个算法

  • mismatchpartition_copy返回来自不同范围的一对迭代器;
  • minmax返回一对可能根本不是迭代器的对象,如果它们不存在则无法保证它们形成范围;
  • minmax_element可以返回一个范围,但也可以返回反转范围(例如,在反向排序的范围minmax_element将返回{prev(last), first};
  • equal_range保证返回范围。

答案 1 :(得分:2)

我不认为它会像开箱即用那样工作,因为equal_range返回一对迭代器,而documentation的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函数来获取迭代器对并分别返回第一个和第二个函数。

答案 2 :(得分: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;
    }
}

答案 3 :(得分:0)

std::equal_range返回的只是一个std ::对。该标准没有涵盖迭代这些事情的任何方法。

您可能想要阅读的内容是Alexandrescu的"Iterators must go"演示文稿。 Here is the video。阅读更优雅的方法,使用Ranges迭代容器。

范围在他的Loki库中实现。