c++range-based-loop

range-expression of range based for loop in C++


I am trying to pass a pointer of vector to range based for loop for its range-expression.

Here is the syntax of range based for loop:

attr(optional) for ( init-statement(optional) range-declaration : range-expression )
loop-statement

Referenced from cppreference.com:

range-expression is evaluated to determine the sequence or range to iterate. Each element of the sequence, in turn, is dereferenced and is used to initialize the variable with the type and name given in range-declaration.

begin-expr and end-expr are defined as follows:

    If range-expression is an expression of array type, then begin-expr is __range and end-expr is (__range + __bound), where __bound is the number of elements in the array (if the array has unknown size or is of an incomplete type, the program is ill-formed)
    If range-expression is an expression of a class type C that has both a member named begin and a member named end (regardless of the type or accessibility of such member), then begin-expr is __range.begin() and end-expr is __range.end();
    Otherwise, begin-expr is begin(__range) and end-expr is end(__range), which are found via argument-dependent lookup (non-ADL lookup is not performed). 

I defined begin and end and expect them to be used for begin-expr, to dereference the pointer, but failed. Here is my codes:

#include <iostream>                // std::cout
#include <vector>
using namespace std;

vector<int>::iterator
begin(vector<int> *a)
{
   return a->begin();
}

vector<int>::iterator
end(vector<int> *a)
{
   return a->end();
}

int main()
{
    vector<int> v = {1,2,3,4};
    vector<int> *p = &v;
    for (auto i : p) {
        cout << i << endl;
    }
    return 0;
}

I am still getting the below compile error:

Invalid range expression of type 'vector<int> *'; did you mean to dereference it with '*'?

Is there anything I missed here?


Solution

  • Otherwise, begin-expr is begin(__range) and end-expr is end(__range), which are found via argument-dependent lookup (non-ADL lookup is not performed).

    begin() and end() are looked up only via ADL. For pointers, it works like this:

    For arguments of type pointer to T or pointer to an array of T, the type T is examined and its associated set of classes and namespaces is added to the set.

    The only namespace associated with std::vector<int> is namespace std, so that's where begin() and end() will be looked up.

    Putting begin() and end() into namespace std makes the code work, but adding new declarations into std causes undefined behavior (with a few exceptions), and shouldn't be done.