为具有“结束”成员变量的类型启用基于范围的

时间:2019-05-03 17:32:14

标签: c++ c++11

我正在使用a vector type,它来自C库,外观类似于

struct Vec {
    int *stor_begin;
    int *stor_end;
    int *end;
};

我试图通过创建免费的begin()end()函数来为此类型启用基于范围的for循环,但是我从clang中得到了这个错误:

  

错误:范围类型'igraph_vector_int_t'具有'end'成员但没有'begin'成员

是否有一种方法(使用C ++ 11)为这种类型(我不能直接修改)启用基于范围的for循环?


这是一个演示问题的最小示例:

// No problems with Foo

struct Foo {
    int *fooBeg;
    int *fooEnd;
};

int *begin(Foo &foo) { return foo.fooBeg; }
int *end(Foo &foo) { return foo.fooEnd; }

void testFoo(Foo &foo) {
    int sum = 0;
    for (const auto &x : foo)
        sum += x;
}

// Bar does not work because it has a member variable called 'end'

struct Bar {
    int *stor_begin;
    int *end;
};

int *begin(Bar &bar) { return bar.stor_begin; }
int *end(Bar &bar) { return bar.end; }

void testBar(Bar &bar) {
    int sum = 0;
    for (const auto &x : bar)
        sum += x;
}

来自gcc 7.2 / Wandbox的错误:

prog.cc: In function 'void testBar(Bar&)':
prog.cc:26:26: error: range-based 'for' expression of type 'Bar' has an 'end' member but not a 'begin'
     for (const auto &x : bar) {
                          ^~~
prog.cc:26:26: error: expression cannot be used as a function

1 个答案:

答案 0 :(得分:6)

g++ 8.xclang++ 8.x(及更高版本)都编译您的代码:live example on godbolt.org

这很可能是编译器错误。


如评论中的François Andrieux所述,标准规定:

  

[stmt.ranged]

     

1.2.2 (如果 for-range-initializer 是类类型C的表达式,则非限定ID begin和{在end范围内查找{1}},就好像是通过类成员访问查找([basic.lookup.classref]),并且如果两者都找到至少一个声明 begin-expr end-expr 分别为Crange.begin()

     

1.3.3 ,否则, begin-expr end-expr 分别为range.end()begin(range) ,在关联的命名空间([basic.lookup.argdep])中查找begin和end。 [注意:不执行普通的不合格查找([basic.lookup.unqual])。 —尾注]

这似乎与我的假设是错误有关。如果仅找到end(range).begin之一,则1.3.3应该使您的代码格式正确。