[cfe-dev] [clang++][c++11] complier problems about "ranged-based for"

James Dennett james.dennett at gmail.com
Fri Mar 8 15:19:02 PST 2013


On Fri, Mar 8, 2013 at 2:37 PM, ZhangXiongpang <zhangxiongpang at gmail.com> wrote:
> James Dennett wrote
>> On Fri, Mar 8, 2013 at 2:32 AM, ZhangXiongpang <
>
>> zhangxiongpang@
>
>> > wrote:
>>> James Dennett wrote
>>>>> In case (1), where "begin" and "end" are looked up as class members,
>>>>> C++ doesn't allow the syntax object.TypeName,
>>>
>>> I know C++ doesn't allow the syntax "object.TypeName",
>>> but the "object"(__begin) is a also a function object,
>>> it is callable. so why not treat the object as a function?
>>
>> I'm sorry, I don't understand your question.  Are you talking about
>> the case of your test (3), which compiles successfully (as it should),
>> or something else?
>
> I mean in example 1 "begin" and "end" are also callable, just like the
> "begin" and "end" in example 3. The difference between example 1 and example
> 3 is:
> (1) in example 3, there is a member who named "begin" in class X, so it will
> look up "x.begin()" and "x.end()", standard says "begin-expr and end-expr
> are __range.begin() and __range.end(), respectively".

Right, this is why (3) compiles.

> (2) in example 1, no member named "begin" or "end" in class X, so it will
> look up "begin(x)" from the associated namespace of x, standard syas
> "begin-expr and end-expr are begin(__range) and end(__range), respectively".

The standard says that the lookup for name names "begin" and "end" is
ADL in the non-member case, and so the non-functions begin and end are
not found, and the code is erroneous.

Here's a modified example showing that the hand-written loop fails in
the same way if restricted to using ADL + namespace std.

struct X {};
struct Iterator {
    Iterator(int v) : value(v) {}
    int operator++(){ return ++value; }
    int& operator*(){ return value; }
    bool operator!=(const Iterator& iter) { return value != iter.value; }
    int value;
};
struct Functor {
    Functor(int v) : value(v) {}
    Iterator operator()(const X&) { return Iterator(value); }
    int value;
};

Functor begin(1), end(5);

namespace std {
int *begin(int*);
int *end(int*);
}

int main() {
  using std::begin;
  using std::end;

    X x;
    auto&& __range = x; // ok
    for ( auto __begin = begin(__range),  // error: no matching
function for call to 'begin'
          __end = end(__range);
          __begin != __end; ++__begin ) {
        int i = *__begin;
        // ...
    } // ok
    for (int i : x) ; *// error: no viable 'begin' function available*
}

Note that the manually lowered loop fails to compile, for the same
reason as the range-based one: no suitable "begin" is found.



More information about the cfe-dev mailing list