Use of for_each on map elements
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
std::for_each works perfectly well with std::map, because a map exposes standard iterators just like other STL containers. The only extra detail is that each element is a key-value pair whose key is effectively immutable during iteration.
What a Map Element Looks Like
When you iterate over std::map<Key, Value>, each element has type:
That const on the key is important. You can read the key and modify the mapped value, but you cannot assign a new key through the iterator.
Here is a simple read-only example:
std::for_each simply walks the iterators from begin() to end() and applies the lambda to each element.
Modifying the Mapped Value
If you want to change the value part, take the entry by non-const reference:
This is legal because entry.second is mutable.
What is not legal is:
Map keys determine ordering inside the tree structure, so changing them in place would break the container invariants.
for_each Versus Range-Based for
In modern C++, a range-based loop is often simpler:
For straightforward iteration, this is usually easier to read than std::for_each.
std::for_each still makes sense when:
- you are already writing in an algorithm-heavy STL style
- you want to reuse a function object
- you want the operation packaged as a callable unit
It is valid, just not always the clearest choice.
Using a Named Function Object
If the logic is reusable, a named callable can be cleaner than an inline lambda:
This is one reason for_each exists in the first place: algorithms can operate with ordinary function objects, not just explicit loops.
Ordering and Complexity
Because std::map is ordered, iteration visits elements in key order. std::for_each does not change that. It just consumes the iterators in their natural sequence.
If key ordering is not needed, std::unordered_map may be a better container, but the same for_each pattern still applies conceptually.
Erasing While Iterating Needs Care
One trap is trying to erase elements from the map inside a for_each traversal. Structural modification during active iteration is tricky and should be handled with iterator-aware loops or collected keys for later removal.
For example, safer removal often looks like:
That is much safer than erasing from inside a for_each lambda.
Common Pitfalls
The most common mistake is forgetting that the element is a pair, not just the mapped value.
Another common mistake is trying to modify entry.first, which is the key and therefore effectively immutable through map iteration.
A third pitfall is using std::for_each for very simple loops where a range-based for is clearer to most readers.
Finally, be careful with structural modifications such as erase or insert during traversal. If the container itself is changing, an ordinary iterator loop is often the better tool.
Summary
- '
std::for_eachworks normally withstd::mapiterators' - Each map element is a
std::pair<const Key, Value> - You may modify the mapped value, but not the key
- Range-based
forloops are often clearer for simple iteration - Avoid structural container changes inside a
for_eachtraversal unless you are handling iterators very carefully

