Why does std::for_each on a map call the copy constructor? [duplicate]
Question
I have the following simple example, in which I want to call std::for_each
on a collection of objects that are non-copyable:
class A {
public:
A() : x(0) {}
A(const A&) = delete;
private:
int x;
};
void func() {
std::vector<A> v(10);
std::map<int, A> m;
// works as expected
std::for_each(begin(v), end(v), [](const A& a) { /* do nothing */ });
// error calling copy constructor
std::for_each(begin(m), end(m), [](const std::pair<int, A>& a) { /* do nothing */ });
}
If I put everything into a std::vector
, it works as I expected, but when using a std::map
, suddenly std::for_each
wants to call the (deleted) copy constructor. Why? I would have assumed that I simply get a reference to the pair that is saved in the map, without any necessary copies.
Solution
The problem is that std::map
has a std::pair<const Key, Value>
as its internal value type. Rather than explicitly specifying this, Standard Library containers allow you to extract this from the container type:
In C++11 do (same as in C++98, but you would have to use a function object rather than a lambda inside for_each
, and also use typedef
instead of using =
):
using value_type = std::map<int, A>::value_type;
std::for_each(begin(m), end(m), [](value_type const& a) { /* do nothing */ });
In C++14 do:
std::for_each(begin(m), end(m), [](auto const& a) { /* do nothing */ });
The use of auto
inside the lambda is supported by Clang 3.4, Visual Studio 2013 November CTP, and GCC 4.9.