标签:
for ( declaration : expression ) statement0.1 根据标准将会扩展成这样的形式:
1 { 2 auto&& __range = expression; 3 for (auto __begin = begin-expression, 4 __end = end-expression; 5 __begin != __end; 6 ++__begin) 7 { 8 declaration = *__begin; 9 statement 10 } 11 }
The begin-expression and end-expression (lines 3 and 4) are determined as follows:
__range
and __range + __bound
, respectively, where __bound
is the array bound.begin()
and end()
member functions, then begin-expression and end-expression are__range.begin()
and __range.end()
, respectively.begin(__range)
and end(__range)
, respectively, where the begin()
and end()
functions are looked up using the argument-dependent lookup (ADL) which also includes the std
namespace.With arrays taken care of by the first rule, the second rule makes sure that all the standard containers as well as all the user-defined ones that follow the standard sequence interface will work with range-based for
out of the box. For example, in ODB (an ORM for C++), we have the container-like result
class template which allows iteration over the query result. Because it has the standard sequence interface with a forward iterator, we didn’t have to do anything extra to make it work with range-based for
.
The last rule (the fallback to the free-standing begin()
and end()
functions) allows us to non-invasively adapt an existing container to the range-based for
loop interface.
std::vector<int> v = {1, 2, 3, 5, 7, 11}; const std::vector<int> cv = {1, 2, 3, 5, 7, 11}; for (auto x: v) // x is int ...; for (auto x: cv) // x is int ...; for (auto& x: v) // x is int& ...; for (auto& x: cv) // x is const int&
for
(
auto
a : a_vec)
{
}
for
(const
auto&
a : a_vec)
{
}
3. 一个实现了 container semantics 的例子:
3.1 simple iterator
template <typename T> struct reverse_range { private: T& x_; public: reverse_range (T& x): x_ (x) {} auto begin () const -> decltype (this->x_.rbegin ()) { return x_.rbegin (); } auto end () const -> decltype (this->x_.rend ()) { return x_.rend (); } }; template <typename T> reverse_range<T> reverse_iterate (T& x) { return reverse_range<T> (x); } std::vector<int> v = {1, 2, 3, 5, 7, 11}; for (auto x: reverse_iterate (v))
#include <memory>
#include <iterator>
/* Only provides the bare minimum to support range-based for loops.
Since the internal iterator of a range-based for is inaccessible,
there is no point in more functionality here. */
template< typename iter >
struct range_iterator_reference_wrapper
: std::reference_wrapper< iter > {
iter &operator++() { return ++ this->get(); }
decltype( * std::declval< iter >() ) operator*() { return * this->get(); }
range_iterator_reference_wrapper( iter &in )
: std::reference_wrapper< iter >( in ) {}
friend bool operator!= ( range_iterator_reference_wrapper const &l,
range_iterator_reference_wrapper const &r )
{ return l.get() != r.get(); }
};
namespace unpolluted {
/* Cannot call unqualified free functions begin() and end() from
within a class with members begin() and end() without this hack. */
template< typename u >
auto b( u &c ) -> decltype( begin( c ) ) { return begin( c ); }
template< typename u >
auto e( u &c ) -> decltype( end( c ) ) { return end( c ); }
}
template< typename iter >
struct range_proxy {
range_proxy( iter &in_first, iter in_last )
: first( in_first ), last( in_last ) {}
template< typename