Both can be used to apply a function to a range of elements.
On a high level:
std::for_each
ignores the return value of the function, and
guarantees order of execution.std::transform
assigns the return value to the iterator, and does
not guarantee the order of execution.When do you prefer using the one versus the other? Are there any subtle caveats?
std::transform
is the same as map
. The idea is to apply a function to each element in between the two iterators and obtain a different container composed of elements resulting from the application of such a function. You may want to use it for, e.g., projecting an object's data member into a new container. In the following, std::transform
is used to transform a container of std::string
s in a container of std::size_t
s.
std::vector<std::string> names = {"hi", "test", "foo"};
std::vector<std::size_t> name_sizes;
std::transform(names.begin(), names.end(), std::back_inserter(name_sizes), [](const std::string& name) { return name.size();});
On the other hand, you execute std::for_each
for the sole side effects. In other words, std::for_each
closely resembles a plain range-based for
loop.
Back to the string example:
std::for_each(name_sizes.begin(), name_sizes.end(), [](std::size_t name_size) {
std::cout << name_size << std::endl;
});
Indeed, starting from C++11 the same can be achieved with a terser notation using range-based for
loops:
for (std::size_t name_size: name_sizes) {
std::cout << name_size << std::endl;
}