In such a range based for:
for ( for-range-declaration : expression ) statement
the standard says that the compiler looks for either members ((expression).begin()
, (expression).end()
) or free functions (begin((expression))
, end((expression))
) if expression is of class type.
Therefore you can either provide member functions OR free functions (which need to be in scope for argument dependant lookup).
C++11, § 6.5.4 [stmt.ranged]
This is what a ranged-based for does according to the standard:
for ( for-range-declaration : expression ) statement
range-init = ( expression )
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin )
{
for-range-declaration = *__begin;
statement
}
}
The begin-expr
and end-expr
are described as:
if _RangeT
is an array type, begin-expr and end-expr are _range and _range + _bound, respectively, where _bound is the array bound. If _RangeT is an array of unknown size or an array of incomplete type, the program is ill-formed;
if _RangeT
is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, beginexpr and end-expr are __range.begin() and __range.end(), respectively;
otherwise, begin-expr and end-expr are begin(__range)
and end(__range)
, respectively, where begin
and end
are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespace std is an associated namespace.