This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [C++0x] Range-based for statements and ADL
On 17 March 2011 18:18, Jonathan Wakely wrote:
> On 17 March 2011 18:09, Rodrigo Rivas wrote:
>> Hello all.
>>
>> I've just read the paper titled "Range-based for statements and ADL"
>> by Jonathan Wakely and Bjarne Stroustrup at:
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3257.pdf
>>
>> The point of this article is that the argument dependent lookup in the
>> range-for specification will make some trouble in the real world. E.g:
>> #include <vector>
>> namespace n
>> {
>> ? ?struct X { void begin(); };
>> ? ?struct Y { void begin(); };
>> ? ?template<typename T> void begin(T& t) { t.begin(); }
>> }
>> int main()
>> {
>> ? ?std::vector<n::X> v;
>> ? ?for (auto i : v) ?// error: call to begin is ambiguous: std::begin
>> or n::begin?
>> ? ?{
>> ? ? ? ?//...
>> ? ?}
>> }
>>
>> I've implemented Option 5 from the paper (which is the coolest, IMHO):
>> ?- [...], if _rangeT has a member begin or a member end, begin-expr
>> 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 [...]
>>
>> I'm not sure about what should happen if _rangeT has a member begin
>> but not a member end. I think that there are just two sensible
>> options:
>> ?* Use them only if both members, begin and end, exist.
>> ?* Look for them independently. This is what my patch does.
>>
>> Also, if the member begin/end is not accessible or not callable, a
>> compiler error will follow immediately (this is as expected).
>>
>> I'll appreciate any comments.
>
> Hi Rodrigo,
>
> do you mind if I forward your mail to the committee reflector? ?The
> fact that there's an implementation is useful.
>
> I think Bjarne's intention is that the lookup is independent and if
> one is found but not the other, or if they do not have the right
> semantics (i.e. they just happen to be called "begin" and "end" but
> are not STL-style range functions returning iterators) then it should
> be an error. ?So I think what you've done is correct.
>
> Bjarne said:
>
> Maybe I was being obscure and clearly I should have added a rationale
> (thanks), but I actually think that if you try to use a range-for a
> class that has "odd" begin and/or end, it should be an error, rather
> than "silently" start looking in the enclosing name space. Consider
>
> ? ?struct C {
> ? ? ? ?int* begin();
> ? ? ? ?// I forgot end() or misspelled end() or gave end the wrong type
> ? ?};
>
> ? ?C cont;
> ? ?// ...
> ? ?template<class T> T* begin(T); ? ?// the nastiest example I could
> come up with in a hurry
> ? ?template<class T> T* end(T);
> ? ?// ...
> ? ?for (auto x : cont ) // I'd prefer this to fail
>
Actually, re-reading that and the following messages on the thread,
I'm wrong about the lookup being independent - if it only finds a
begin() member and no end() member it should still try to use r.end(),
and therefore give an error. It should not be possible to use
r.begin() and end(r)