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

Platform: linux, x86_64, clang++3.2

6.5.4/p1:

I think that the Standard is clear on this (well, as clear as it ever
is), and that Clang appears to implement this correctly.

In case (1), where "begin" and "end" are looked up as class members,
C++ doesn't allow the syntax object.TypeName, so the only interesting
case is your example 3, where range.begin and range.end are callable
data members. As your tests show, Clang permits that.

In case (2), "begin" and "end" are found via argument-dependent
lookup, which only finds function (and function template) names. You
can add "using std::begin; using std::end;" inside your functions that
emulate range-based "for" to prevent finding the globals via non-ADL
lookup and more accurately emulate the semantics of range-based for
(and hence will not compile).

-- James

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?

James Dennett wrote

In case (2), "begin" and "end" are found via argument-dependent
lookup, which only finds function (and function template) names.

I'm confused that if standard only permit implement to find function,
why not explicitly saying that "begin" and "end" shall be functions?

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?

James Dennett wrote

In case (2), "begin" and "end" are found via argument-dependent
lookup, which only finds function (and function template) names.

I'm confused that if standard only permit implement to find function,
why not explicitly saying that "begin" and "end" shall be functions?

Because it doesn't need to. The Standard is not a tutorial, and tries
to avoid redundancy.

-- James

James Dennett 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".
(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".

James Dennett 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.

I understand. Thanks very much for your answer!

James Dennett wrote