vectors librerias libreria iterador estandar ejemplos ejemplo dev c++ stl stl-algorithm

c++ - librerias - La compostabilidad de los algoritmos STL



vector stl c++ ejemplos (3)

Creo que el problema lamentablemente es estructural

  1. C ++ usa dos iteradores para representar una secuencia
  2. Las funciones de C ++ son de un solo valor

por lo que no puede encadenarlos porque una función no puede devolver "una secuencia".

Una opción habría sido usar secuencias de un solo objeto en su lugar ( como el enfoque de rango de impulso ). De esta forma, podría haber combinado el resultado de un procesamiento como la entrada de otro ... (un objeto -> un objeto).

En la biblioteca estándar de C ++, en cambio, el procesamiento es (dos objetos -> un objeto) y está claro que no se puede encadenar sin nombrar el objeto temporal.

Los algoritmos de STL son bastante útiles en C ++. Pero una cosa que me molesta es que parecen carecer de capacidad de compilación.

Por ejemplo, supongamos que tengo un vector<pair<int, int>> y quiero transformarlo en un vector<int> contenga solo el second miembro del par. Eso es bastante simple:

std::vector<std::pair<int, int>> values = GetValues(); std::vector<int> result; std::transform(values.begin(), values.end(), std::back_inserter(result), [] (std::pair<int, int> p) { return p.second; });

O tal vez quiero filtrar el vector solo para aquellos pares cuyo first miembro sea par. También bastante simple:

std::vector<std::pair<int, int>> values = GetValues(); std::vector<std::pair<int, int>> result; std::copy_if(values.begin(), values.end(), std::back_inserter(result), [] (std::pair<int, int> p) { return (p.first % 2) == 0; });

Pero, ¿y si quiero hacer ambas cosas? No existe un algoritmo transform_if , y el uso de transform y copy_if parece requerir la asignación de un vector temporal para mantener el resultado intermedio:

std::vector<std::pair<int, int>> values = GetValues(); std::vector<std::pair<int, int>> temp; std::vector<int> result; std::copy_if(values.begin(), values.end(), std::back_inserter(temp), [] (std::pair<int, int> p) { return (p.first % 2) == 0; }); std::transform(values.begin(), values.end(), std::back_inserter(result), [] (std::pair<int, int> p) { return p.second; });

Esto me parece un desperdicio. La única forma en que puedo pensar para evitar el vector temporal es abandonar transform y copy_if y simplemente usar for_each (o un bucle for normal, lo que más te guste):

std::vector<std::pair<int, int>> values = GetValues(); std::vector<int> result; std::for_each(values.begin(), values.end(), [&result] (std::pair<int, int> p) { if( (p.first % 2) == 0 ) result.push_back(p.second); });

¿Me estoy perdiendo de algo? ¿Hay una buena manera de componer dos algoritmos STL existentes en uno nuevo sin necesidad de almacenamiento temporal?



Ya en 2000, el problema ya se notó. Gary Powell y Martin Weiser presentaron un concepto de "vista" y acuñaron el nombre "Ver biblioteca de plantillas". No despegó entonces, pero la idea tiene sentido. Un adaptador de "vista" aplica esencialmente una transformación sobre la marcha. Por ejemplo, puede adaptar el value_type .

El concepto probablemente debería volver a tratarse ahora que tenemos C ++ 0x. Avanzamos bastante en la programación genérica desde 2000.

Por ejemplo, usemos el ejemplo de vector<pair<int, int>> to vector<int> . Eso podría ser bastante simple:

std::vector<std::pair<int, int>> values = GetValues(); vtl2::view v (values, [](std::pair<int, int> p) { return p.first }); std::vector<int> result(view.begin(), view.end());

O, usando las técnicas boost::bind , aún más simple:

std::vector<std::pair<int, int>> values = GetValues(); vtl2::view v (values, &std::pair<int, int>::first); std::vector<int> result(view.begin(), view.end());