Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use range-based for loops with iterator ranges?

Tags:

c++

c++11

stl

Consider the usage with std::multimap, where I am given a range of iterators:

std::unordered_multimap<std::string, MyObject> mymap;

auto& range = mymap.equal_range("some_key");
for (auto& the_pair : range)
{
}

Now, the code above does not compile, but I am using it for demonstration purposes. Is it possible to use range-based for loops with a pair of iterators like this? I don't imagine it is possible directly, so I guess my question is really about whether or not there is an adapter class in STL for this use case. I could probably write my own but this seems like a common case.

Update:

If this is not a common case and STL does not provide such a proxy or adapter for this type of usage, what is required to implement them? I was thinking that I'd need to overload the free functions begin and end and also define an adapter iterator class for std::pair<T,U>. I'm just taking a conceptual stab at it, but please let me know! Thanks in advance everyone.

like image 686
void.pointer Avatar asked Dec 15 '22 16:12

void.pointer


2 Answers

No, range-based for calls std::begin and std::end. There isn't any overloads for std::pair. At one point, this feature existed in a draft standard but was removed. You can write your own code. Stealing from sellibitze:

template<class Iter>
struct iter_pair_range : std::pair<Iter,Iter> {
    iter_pair_range(std::pair<Iter,Iter> const& x)
    : std::pair<Iter,Iter>(x)
    {}
    Iter begin() const {return this->first;}
    Iter end()   const {return this->second;}
};

template<class Iter>
inline iter_pair_range<Iter> as_range(std::pair<Iter,Iter> const& x)
{ return iter_pair_range<Iter>(x); }

int main() {
    std::unordered_multimap<std::string, MyObject> mymap;

    auto range = mymap.equal_range("some_key");
    for (auto& the_pair : as_range(range))
    {
    }
}

You can look at n2995 from 2009 which talks about adding ranged support to the standard library. Maybe you're better off using Boost.Range.

like image 166
user4689757 Avatar answered Jan 26 '23 01:01

user4689757


The template-based answer is probably what you are looking for, but i would use a for_each instead with a lambda. It is cleaner and easier to digest.

like image 43
Rado Avatar answered Jan 26 '23 00:01

Rado