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:
- The lookup rules for begin/end in a range-based for loop say that begin/end are looked for in 1) as member functions of the range object 2) as free functions in "associated namespaces"
std::pair
does not have begin/end member functions- The only associated namespace for
std::pair<T, U>
in general is namespace std - We are not allowed to overload
std::begin
/std::end
forstd::pair
ourselves - We cannot specialize
std::begin
/std::end
forstd::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?
expanding on the above answer using c++11 optimisations:
You can use
boost::make_iterator_range
. It constructs an iterator_range withbegin()
andend()
methods.boost::make_iterator_range
can acceptstd::pair
of iterators.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:
(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.