No, a ranged-for loop does not use operator[]
The definition of
for ( range_declaration : range_expression ) loop_statement
Is that it is treated as-if it were (without introducing __names
)
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
With the following rules for begin_expr
and end_expr
:
- If
range_expression
is an expression of array type, then begin_expr
is __range
and end_expr
is (__range + __bound)
,
where __bound
is the number of elements in the array (if the array
has unknown size or is of an incomplete type, the program is
ill-formed)
- If range_expression is an expression of a class type
C
that has both a member named begin
and a member named end
(regardless of
the type or accessibility of such member), then begin_expr
is
__range.begin()
and end_expr
is __range.end()
;
- Otherwise,
begin_expr
is begin(__range)
and end_expr
is end(__range)
, which are found via argument-dependent lookup (non-ADL
lookup is not performed).
A simple change to your class which would suffice would to be add begin
and end
, delegating to m.begin()
and m.end()
class C {
private:
std::unordered_map<char, int> m = {{'a', 1}, {'b', 2}, {'c', 3}};
public:
int operator[](const char& key) const {
return m.find(key)->second;
// return m.at(key); or return m[key]; are both safer than this
}
std::unordered_map<char, int>::iterator begin() {
return m.begin();
}
// overloaded on the constness of "this"
std::unordered_map<char, int>::const_iterator begin() const {
return m.begin();
}
std::unordered_map<char, int>::iterator end() {
return m.end();
}
// overloaded on the constness of "this"
std::unordered_map<char, int>::const_iterator end() const {
return m.end();
}
};