¿Por qué std::for_each en un mapa llama al constructor de copia?[duplicar]
Pregunta
Tengo el siguiente ejemplo simple, en el que quiero llamar std::for_each
en una colección de objetos que no se pueden copiar:
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 */ });
}
Si pongo todo en un std::vector
, funciona como esperaba, pero cuando uso un std::map
, de repente std::for_each
quiere llamar al constructor de copia (eliminado).¿Por qué?Habría asumido que simplemente obtengo una referencia al par que está guardado en el mapa, sin ninguna copia necesaria.
Solución
El problema es ese std::map
tiene un std::pair<const Key, Value>
como su tipo de valor interno.En lugar de especificar esto explícitamente, los contenedores de la Biblioteca estándar le permiten extraerlo del tipo de contenedor:
En C++ 11 hazlo (igual que en C++ 98, pero tendrías que usar un objeto de función en lugar de una lambda dentro for_each
, y también utilizar typedef
en lugar de using =
):
using value_type = std::map<int, A>::value_type;
std::for_each(begin(m), end(m), [](value_type const& a) { /* do nothing */ });
En C++14 haz:
std::for_each(begin(m), end(m), [](auto const& a) { /* do nothing */ });
El uso de auto
El interior de lambda es compatible con Clang 3.4, Visual Studio 2013 November CTP y GCC 4.9.