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)

Reply via email to