Range-based for statement definition redundancy
argument-dependent-lookup, c++, c++11, for-loop, range
Solution
This avoids a corner-case with ADL:
namespace other {
struct T {};
int begin(T*) { return 42; }
}
other::T a[3];
for (auto v : a) {}
Because ADL finds other::begin when calling `begin(a)`, the equivalent code would break causing a confusing compile error (along the lines of "can't compare int to other::T*" as `end(a)` would return a T*) or different behavior (if other::end was defined and did something likewise unexpected).
Problem
Looking at n3092, in §6.5.4 we find the equivalency for a range-based for loop. It then goes on to say what `__begin` and `__end` are equal to. It differentiates between arrays and other types, and I find this redundant (aka confusing). It says for arrays types that `__begin` and `__end` are what you expect: a pointer to the first and a pointer to one-past the end. Then for other types, `__begin` and `__end` are equal to `begin(__range)` and `end(__range)`, with ADL. Namespace `std` is associated, in order to find the `std::begin` and `std::end` defined in `<iterator>`, §24.6.5. However, if we look at the definition of `std::begin` and `std::end`, they are both defined for arrays as well as container types. And the array versions do exactly the same as above: pointer to the first, pointer to one-past the end. Why is there a need to differentiate arrays from other types, when the definition given for other types would work just as well, finding `std::begin` and `std::end`? Some abridged quotes for convenience: §6.5.4 The range-based `for` statement — 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. — 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. §24.6.5 range access ``` template <class T, size_t N> T* begin(T (&array)[N]); ``` Returns: array. ``` template <class T, size_t N> T* end(T (&array)[N]); ``` Returns: array + N.