Range-based for loop and ADL

  • Thread starter Johannes Schaub (litb)
  • Start date
J

Johannes Schaub (litb)

Range-based for loop description says 6.5.4/1:

"... 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)."

And 3.4.2 says at 3.4.2/3:

"Let X be the lookup set produced by unqualiï¬ed lookup (3.4.1) and let Y be
the lookup set produced by argument dependent lookup (deï¬ned as follows). If
X contains

- a declaration of a class member, or
- a block-scope function declaration that is not a using-declaration, or
- a declaration that is neither a function or a function template

then Y is empty. Otherwise Y is the set of declarations found in the
namespaces associated with the argument types as described below. The set of
declarations found by the lookup of the name is the union of X and Y"


WTF!? Now is the following code valid? I.e is the set of declarations found
the union of X and Y or is it only Y?!

struct Foo {
typedef int *iterator;
int *begin() { return array; }
int *end() { return array + 2; }

int array[2];
};

namespace ranges {
template<typename T>
typename T::iterator begin(T &t) { return t.begin(); }

template<typename T>
typename T::iterator end(T &t) { return t.end(); }
}

int main() {
// Is "X" included in the set of declarations found!?
using ranges::begin;
using ranges::end;

Foo f = { 1, 2 };
for(int a : f)
;
}
 
A

Alf P. Steinbach /Usenet

* Johannes Schaub (litb), on 05.09.2010 21:34:
Range-based for loop description says 6.5.4/1:

"... 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)."

And 3.4.2 says at 3.4.2/3:

"Let X be the lookup set produced by unqualiï¬ed lookup (3.4.1) and let Y be
the lookup set produced by argument dependent lookup (deï¬ned as follows). If
X contains

- a declaration of a class member, or
- a block-scope function declaration that is not a using-declaration, or
- a declaration that is neither a function or a function template

then Y is empty. Otherwise Y is the set of declarations found in the
namespaces associated with the argument types as described below. The set of
declarations found by the lookup of the name is the union of X and Y"


WTF!? Now is the following code valid? I.e is the set of declarations found
the union of X and Y or is it only Y?!

It's always the union of X and Y; the only question is whether Y is empty (ADL
lookup not performed).


struct Foo {
typedef int *iterator;
int *begin() { return array; }
int *end() { return array + 2; }

int array[2];
};

namespace ranges {
template<typename T>
typename T::iterator begin(T&t) { return t.begin(); }

template<typename T>
typename T::iterator end(T&t) { return t.end(); }
}

int main() {
// Is "X" included in the set of declarations found!?
using ranges::begin;
using ranges::end;

Foo f = { 1, 2 };
for(int a : f)
;

Here unqualified lookup producing set X finds the 'begin' and 'end' introduced
by the 'using' declarations, so they're in the set X, but this is not
sufficient to prohibit ADL. And so ADL is performed. However, ADL finds nothing
(I think), and so Y is empty.

The union of X and Y is then identical to X.

And in set X you have the 'begin' and 'end' introduced by the 'using' declarations.




Cheers & hth.,

- Alf
 
J

Johannes Schaub (litb)

Alf said:
* Johannes Schaub (litb), on 05.09.2010 21:34:

It's always the union of X and Y; the only question is whether Y is empty
(ADL lookup not performed).

That's the interpretation I would like the spec to intend. But it says
"looked up with argument-dependent lookup", and "let Y be the lookup set
produced by argument dependent lookup (defined as follows). ... Y is the set
of declarations found in the namespaces associated with the argument types
as described below."

This seems to say that only Y is taken for the set of declarations for
begin/end. The sentence "The set of declarations found by the lookup of the
name is the union of X and Y" surely sounds weird to me. Why does it define
what the lookup set of argument dependent lookup *is* and then define it a
second time? What i suspect is that this second sentence is meant to define
the lookup set where ADL is entered by unqualified lookup (i.e by 3.4.1/3 -
that paragraph defines the entire lookup-set by the ADL paragraphs!).

But nonetheless, I really find this absolutely confusing. I tested GCC's
current implementation of this (there is a patch available), and it ignores
local declarations, seemingly ignoring X.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top