Reputation: 25703
I am working with a vector type that comes from a C library and looks similar to
struct Vec {
int *stor_begin;
int *stor_end;
int *end;
};
I tried to enable range-based for loop for this type by creating free begin()
and end()
functions, but I am getting this error from clang:
error: range type 'igraph_vector_int_t' has 'end' member but no 'begin' member
Is there a way (using C++11) to enable range-based for loops for such a type (which I cannot modify directly)?
Here is a minimal example that demonstrates the problem:
// 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;
}
Error from 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
Upvotes: 4
Views: 168
Reputation: 93264
g++ 8.x
and clang++ 8.x
(and newer) both compile your code: live example on godbolt.org.
This is very likely to be a compiler bug.
As François Andrieux mentioned in the comments, the Standard says:
1.2.2 if the for-range-initializer is an expression of class type
C
, the unqualified-idsbegin
andend
are looked up in the scope ofC
as if by class member access lookup ([basic.lookup.classref]), and if both find at least one declaration, begin-expr and end-expr arerange.begin()
andrange.end()
, respectively;1.3.3 otherwise, begin-expr and end-expr are
begin(range)
andend(range)
, respectively, where begin and end are looked up in the associated namespaces ([basic.lookup.argdep]). [ Note: Ordinary unqualified lookup ([basic.lookup.unqual]) is not performed. — end note ]
This seems to agree with my hypothesis of this being a bug. If only one of .begin
and .end
is found, then 1.3.3 should make your code well-formed.
Upvotes: 6