I just discovered that at one point, the C++11 draft had std::begin
/std::end
overloads for std::pair
that allowed treating a pair of iterators as a range suitable for use in a range-based for loop (N3126, section 20.3.5.5), but this has since been removed.
Does anyone know why it was removed?
I find the removal very unfortunate, because it seems there is no other way to treat a pair of iterators as a range. Indeed:
std::pair
does not have begin/end member functionsstd::pair<T, U>
in general is namespace stdstd::begin
/std::end
for std::pair
ourselvesstd::begin
/std::end
for std::pair
(because the specialization would have to be partial and that's not allowed for functions)Is there some other way that I am missing?
Remarks. Use the range-based for statement to construct loops that must execute through a range, which is defined as anything that you can iterate through—for example, std::vector , or any other C++ Standard Library sequence whose range is defined by a begin() and end() .
C++11 introduced the ranged for loop. This for loop is specifically used with collections such as arrays and vectors. Here, the ranged for loop iterates the array num from beginning to end. The int variable var stores the value of the array element in each iteration.
Range-based for loop in C++ Range-based for loop in C++ is added since C++ 11. It executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.
I think the 2009 paper "Pairs do not make good ranges" by Alisdair Meredith is at least part of the answer. Basically, many algorithms return pairs of iterators that are actually not guaranteed to be valid ranges. It seems they removed the support for pair<iterator,iterator>
from the for-range loop for this reason. However, the proposed solution has not been fully adopted.
If you know for certain that some pair of iterators really represents a valid range then you could wrap them into a custom type which offers begin()/end() member functions:
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() { multimap<int,int> mm; ... for (auto& p : as_range(mm.equal_range(42))) { ... } }
(untested)
I agree this is a bit of a wart. Functions which return valid ranges (like equal_range) should say so using an appropriate return type. It's a bit embarrasing that we have to manually confirm this via something like as_range
above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With