C++11 循环的开始/结束成员变量和基于范围

C++11 循环的开始/结束成员变量和基于范围,c++11,for-loop,C++11,For Loop,以下代码按预期编译良好: struct delimited_range { int* b; int* e; }; int* begin(delimited_range x) { return x.b; } int* end(delimited_range x) { return x.e; } int main() { delimited_range r; for (int x : r); } 但是,如果我将成员变量的名称更改为begin/end,如 struct deli

以下代码按预期编译良好:

struct delimited_range {
   int* b; int* e;
};

int* begin(delimited_range x) { return x.b; }
int* end(delimited_range x) { return x.e; }

int main() {
   delimited_range r;
   for (int x : r);
}
但是,如果我将成员变量的名称更改为
begin
/
end
,如

struct delimited_range {
   int* begin; int* end;
};

int* begin(delimited_range x) { return x.begin; }
int* end(delimited_range x) { return x.end; }

int main() {
   delimited_range r;
   for (int x : r);
}
我在GCC和Clang中都遇到编译错误。我的理解是,由于
delimited\u range
没有成员函数
begin()
end()
,因此基于范围的for循环在这两种情况下都应该使用非成员函数,但编译器似乎正试图将成员变量用作函数

使用GCC4.8.3,我可以

fail.cpp: In function ‘int main()’:
fail.cpp:10:17: error: expression cannot be used as a function
    for (int x : r);
                 ^
fail.cpp:10:17: error: expression cannot be used as a function
随着叮当声3.4我明白了

main.cpp:10:15: error: called object type 'int *' is not a function or function pointer
   for (int x : r);
              ^
main.cpp:10:15: note: when looking up 'begin' function for range expression of type 'delimited_range'
   for (int x : r);
              ^
1 error generated.

这是编译器中的错误还是标准中的错误?

在§6.5.4/1的上下文中:

对于窗体的基于范围的For语句

for ( for-range-declaration : expression ) statement
for ( for-range-declaration : braced-init-list ) statement
range init
等价于 括号
(表达式)
和基于范围的for语句 形式

for ( for-range-declaration : braced-init-list ) statement
范围初始化
等效于带括号的初始化列表。各 在这种情况下,基于范围的for语句相当于

{
    auto && __range = range_expression ; 
    for (auto __begin = begin_expr,
        __end = end_expr; 
        __begin != __end; ++__begin) { 
        range_declaration = *__begin; 
        loop_statement 
    } 
}
鉴于
\u range
是表达式的类型,本标准解释如下:

如果_range是一种类类型,则在类_range的范围内查找非限定ID begin和end,就像通过类成员访问查找(3.4.5)一样,如果其中一个(或两者)找到至少一个声明,begin-expr和end expr分别是_range.begin()和_range.end()


这不是一个编译器错误。正确查找并选择了
开始
结束
不合格ID。不幸的是,在您的例子中它们不是函数,因此编译器应该触发错误。

编译器将首先在类中查找
开始
结束
成员函数,然后再尝试查找全局函数。

关键是没有成员函数,所以我的第一个期望是,
begin
end
字段将被忽略。