2011-11-14 45 views
7

iteración en un vector que funciona:std :: for_each sobre std :: set, C++ 11

std::vector<int> collection = {2, 3, 4, 5435345, 2}; 
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;}); 

pero no más de un conjunto (Error de compilación):

std::set<int> collection = {2, 3, 4, 5435345, 2}; 
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;}); 

Por qué puede' ¿Puedo iterar sobre std::set con std::for_each?

Bono pregunta: También, me gustaría cambiar el int& en el argumento de la lambda para auto&, ¿por qué no puede deducirse automáticamente esto?

Respuesta

19

std::set<T>::value_type es T const, no T; en consecuencia, el argumento para su lambda debe ser un tipo de valor (es decir, copia) o int const& (y técnicamente, o int const volatile&), no int&. Es decir, que esto funciona: pregunta

std::set<int> collection{2, 3, 4, 5435345, 2}; 
std::for_each(
    collection.begin(), 
    collection.end(), 
    [](int const& i) { std::cout << i << std::endl; } 
); 

Bonus: También, me gustaría cambiar el int& en el argumento de la lambda para auto&, ¿por qué no puede deducirse automáticamente esto?

Porque el estándar dice que no puede; históricamente, creo que esto se debió a interacciones excesivamente complicadas entre lambdas y conceptos (antes de que los conceptos se eliminaran del borrador). Sin embargo, escucho rumores de que los primeros informes de defectos al nuevo estándar (C++ 11) abordarán exactamente esto, por lo que es posible que veas soporte para esto agregado al compilador de tu elección dentro de uno o dos años. EDIT: Oh, mira, C++ 14 ahora tiene lambdas polimórficas ...

+0

¿Dónde oíste eso? En el blog de Herb sutter menciona que no agregarán lambda polimórfica hasta que se haya resuelto el problema de los conceptos, porque todavía quieren una característica similar a conceptos en el futuro. –

+0

lol qué político. :) así que saca eso de la respuesta, ¿quieres? – wilhelmtell

0

Debería poder iterar sobre un conjunto. Sin embargo, tenga en cuenta que dado que el elemento en un conjunto también es su clave, no se puede modificar. Cambie su código para tomar una referencia const, y use cbegin/cend en su lugar, independientemente de si es un conjunto o no cuando no vaya a modificar los elementos.

1

Un iterador set<int> iterador es un const int&. Por lo tanto, no puede pasarlo como un parámetro int& sin el const. Pruebe cualquiera de los planos (int i) o (const int& i).

Y ese no es realmente uno de los lugares en los que está permitido usar auto. Creo que auto solo funciona en una declaración con inicializador o como marcador de posición para un tipo de devolución final.

3

Acerca de la pregunta de bonificación: Un argumento de función "auto" no es específico de lambdas. También podría preguntar por qué no permitimos que todas las funciones se declaren como f(auto x, auto y). Pero eso solo significa que esencialmente desea reemplazar todas las funciones por plantillas de funciones. Se consideró que no funcionaba bien con el lenguaje C++ existente y el sistema de tipos en particular. Si desea una plantilla de función, ya existe una sintaxis y un mecanismo existentes, y declarar argumentos "automáticos" no es el camino a seguir.

Cuestiones relacionadas