以下代码按预期编译正常:
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_range
没有成员函数 begin()
和end()
,因此基于范围的for循环应该在两种情况下都使用非成员函数,但似乎编译器正试图将成员变量用作函数。
GCC 4.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
使用Clang 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.
这是编译器或标准中的错误吗?
答案 0 :(得分:2)
在§6.5.4/ 1的背景下:
对于基于范围的表格形式
for ( for-range-declaration : expression ) statement
让
range-init
等同于包围的表达式 括号( expression )
和基于范围的声明 表格for ( for-range-declaration : braced-init-list ) statement
让
range-init
等同于braced-init-list
。每个 case,基于范围的for语句等同于{ auto && __range = range_expression ; for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } }
并且鉴于_RangeT
是表达式的类型,标准解释了:
如果_RangeT是类类型,则在类_RangeT的范围内查找unqualified-ids的开始和结束,就像通过类成员访问查找(3.4.5)一样,并且如果其中任何一个(或两者)找到至少一个decla,begin-expr和end-expr分别是__range.begin()和__range.end();
这不是编译器错误。正确查找并选择begin
和end
个不合格的ID。不幸的是,它们不是你的情况下的函数,因此编译器应该触发错误。
答案 1 :(得分:1)
在尝试查找全局函数之前,编译器将首先在类中查找begin
和end
成员函数。