Can a range based on loop work on a range

If I have a range (a pair of 2 iterators), there is a way to write a "for each" loop that uses a range rather than an raw array or container.

Something like that:

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

According to Why access to pair ranges is removed from C ++ 11? , you can use an adapter, for example. as_range with the accepted answer boost::make_iterator_range or write your own:

 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)) ... 

The reason this is not applicable at all is because in Alastair Meredith paper , algorithms,

  • mismatch and partition_copy return a pair of iterators from different ranges;
  • minmax returns a pair of objects that cannot be iterators at all, and if they do not guarantee that they form a range;
  • minmax_element can return a range, but it can also return a reverse range (for example, in a range with reverse sorting, minmax_element will return {prev(last), first} ;
  • equal_range guaranteed to return a range.
+13
source

I don’t think this will work the same way that equal_range returns a pair of iterators, but for a loop over a range according to the documentation :

 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. 

I would say that you can define begin and end functions that take a pair of iterators and return the first and second recipe.

+2
source

What std::equal_range returns is just std :: pair. The standard does not cover any method for repeating such actions.

What you can read is Alexandrescu "Iterators Must Go . " Here is the video . Great reading in a more elegant way to iterate over containers using ranges.

Ranges are implemented in his Loki library.

0
source
 #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; } } 
0
source

All Articles