[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