I read this documentation for a range-based for
loop:
The member interpretation is used if the range type has a member named begin and a member named end. This is done regardless of whether the member is a type, data member, function, or enumerator, and regardless of its accessibility. Thus a class like
class meow { enum { begin = 1, end = 2}; /* rest of class */ };
cannot be used with the range-based for loop even if the namespace-scope begin/end functions are present.
I do not understand this paragraph. What does the member interpretation do so as to forbid the example class being used with the range-based for loop?
The "member interpretation" refers to begin_expr
and end_expr
using members of the iterated type in contrast to using plain offsets for arrays or begin
and end
free functions.
The array interpretation is off the table, because it is only used for arrays. Next consider that there is std::begin
and std::end
:
Custom overloads of begin may be provided for classes and enumerations that do not expose a suitable begin() member function, yet can be iterated.
Now consider this example:
#include <iostream>
#include <vector>
class meow {
enum { begin = 1, end = 2};
public:
std::vector<int> data;
};
// non-const iterators
auto begin(meow& m){ return m.data.begin(); }
auto end(meow& m) { return m.data.end(); }
// const iterators
auto begin(const meow& m){ return m.data.begin(); }
auto end(const meow& m) { return m.data.end(); }
int main() {
meow m;
for (const auto& e : m) {}
}
We want to iterate the meow
s data
. But it does not work. The member interpratation is choosen, even though meow::begin
and mewo::end
are private and the begin
and end
functions could be used. Hence the error:
<source>: In function 'int main()':
<source>:17:26: error: 'meow::<unnamed enum> begin' is private within this context
for (const auto& e : m) {}
^
<source>:5:12: note: declared private here
enum { begin = 1, end = 2};
^~~~~
<source>:17:26: error: 'begin' cannot be used as a function
for (const auto& e : m) {}
^
<source>:17:26: error: 'meow::<unnamed enum> end' is private within this context
<source>:5:23: note: declared private here
enum { begin = 1, end = 2};
^~~
<source>:17:26: error: 'end' cannot be used as a function
for (const auto& e : m) {}
^
The example works fine when we remove the private enum:
#include <iostream>
#include <vector>
class meow {
//enum { begin = 1, end = 2};
public:
std::vector<int> data;
};
// non-const iterators
auto begin(meow& m){ return m.data.begin(); }
auto end(meow& m) { return m.data.end(); }
// const iterators
auto begin(const meow& m){ return m.data.begin(); }
auto end(const meow& m) { return m.data.end(); }
int main() {
meow m;
for (const auto& e : m) {}
}