9

範囲(2つのイテレータのペア)がある場合、生の配列やコンテナではなく、範囲を使用する「foreach」ループを作成する方法があります。

このようなもの:

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

4 に答える 4

14

によると、ペア範囲アクセスがC ++ 11から削除されたのはなぜですか?アダプターを使用できます。たとえば、as_range受け入れられた回答で、、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.

イテレータのペアを取り、それぞれ1番目と2番目のイテレータを返す関数を定義beginしてください。end

于 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の「Iteratorsmustgo」プレゼンテーションです。これがビデオです。Rangesを使用してコンテナーを反復処理するためのよりエレガントな方法に関する優れた読み物。

範囲は彼のLokiライブラリに実装されています。

于 2013-03-20T17:22:23.637 に答える