2010-10-07 19 views
22

¿Cómo se hace esto en C++ 0x?std :: transformar utilizando C++ 0x expresión lambda

std::vector<double> myv1; 
std::transform(myv1.begin(), myv1.end(), myv1.begin(), 
       std::bind1st(std::multiplies<double>(),3)); 

pregunta y solución original es here.

+0

.... ¿esto fue tomado de esta otra publicación? http://stackoverflow.com/questions/3885095/c-multiply-vector-elements-by-a-scalar-value-using-stl – ianmac45

+0

@ ianmac45 - sí, he vinculado a esto más arriba –

+0

ah, está bien. se perdió ese – ianmac45

Respuesta

26
std::transform(myv1.begin(), myv1.end(), myv1.begin(), 
    [](double d) -> double { return d * 3; }); 
+20

'-> double' no es necesario; se deduce automáticamente. – Potatoswatter

+4

@potato - se supone que sí, pero los compiladores actuales a veces ignoran este hecho. Mejor ponerlo todo el tiempo. –

+1

Una forma alternativa de esto es: 'std :: transform (myv1.begin(), myv1.end(), myv1.begin(), myv1.end(), std :: bind (std :: multiplicas () , _1,3)); ' –

5

De esta manera:

vector<double> myv1; 
transform(myv1.begin(), myv1.end(), myv1.begin(), [](double v) 
{ 
    return v*3.0; 
}); 
+3

Encuentro ese formato bastante confuso. – Potatoswatter

+2

Para cada uno, supongo. Me apresuro a señalar que el mío * es * el formato correcto. :) –

+1

+1 para realmente usar un doble literal para la constante. ;-) –

26

Eso sí, como Darío dice:

for_each(begin(myv1), end(myv1), [](double& a) { a *= 3; }); 

for_each se le permite modificar los elementos, diciendo que no se trata de un mito.

+1

+1 porque me parece más natural en la pregunta original –

+0

+1 para "for_each se permite modificar elementos". Participé en un debate muy acalorado sobre esto hace años. –

7

Usando un enfoque mutable, podemos usar for_each para actualizar directamente los elementos de secuencia a través de las referencias.

for_each(begin(myv1), end(myv1), [](double& a) { a *= 3; }); 


Ha habido cierto debate sobre si va for_each es en realidad les permite modificar los elementos como se le llama un "no-mutando" algoritmo.

lo que significa que es for_each no está permitido para alterar la secuencia opera sobre (que se refiere a los cambios de la estructura de la secuencia - es decir iteradores invalidantes). Esto no significa que no podamos modificar los elementos no const del vector como de costumbre - la estructura en sí misma no se ve afectada por estas operaciones.

26

La principal motivación original para usar ese estilo funcional para estos casos en C++ fue, "aaagh! Iterator loops!", Y C++ 0x quita esa motivación con la declaración de rango para. Sé que parte del objetivo de la pregunta era descubrir la sintaxis lambda, pero creo que la respuesta a la pregunta "¿Cómo se hace esto en C++ 0x?" es decir:

for(double &a : myv1) { a *= 3; } 

No hay objeto de función real, pero si le ayuda podría pretender que es un { a *= 3; } lambda muy abreviada. Para la usabilidad, equivale a lo mismo en ambos sentidos, aunque el borrador del estándar define el rango en términos de un lazo for equivalente.

+0

Ah yah. Normalmente me olvido de eso ya que no uso un compilador que lo admita. :(Definitivamente la mejor solución. – GManNickG

+0

¿Cuál es el nombre de esta construcción? Todavía no estoy familiarizado con lo que hay en C++ 0x. –

+1

"basado en rango para la declaración", 6.5.4 en n3090. Agregado a la respuesta –

1

Estoy usando VS2012 que admite el adaptador de enlace C++ 11. Para vincular el primer elemento de la función binaria (como bind1st use to do) debe agregar _1 (argumento de marcador de posición). Necesidad de incluir el funcional para bind.

using namespace std::placeholders; 
std::transform(myv1.begin(), myv1.end(), myv1.begin(), 
       std::bind(std::multiplies<double>(),3,_1)); 
Cuestiones relacionadas