2

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?

2
  • 1
    Change the loop to for (auto i : *p) and you don't need to bother with your begin() and end() functions [which won't work, as the lookup of begin() and end() for a range-based loop uses ADL which doesn't work as you want/need for pointers]. Commented Oct 17, 2022 at 4:14
  • 1
    Simpler, just get rid of the pointer altogether: vector<int> v = {1,2,3,4}; for (auto i : v) { ... } Commented Oct 17, 2022 at 5:07

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.