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

时间:2014-08-03 03:45:02

标签: 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 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.

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

2 个答案:

答案 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();

这不是编译器错误。正确查找并选择beginend个不合格的ID。不幸的是,它们不是你的情况下的函数,因此编译器应该触发错误。

答案 1 :(得分:1)

在尝试查找全局函数之前,编译器将首先在类中查找beginend成员函数