2010-04-05 15 views
6

Estoy tratando de resolver un problema que las funciones anónimas hacen mucho, mucho más fácil, y me preguntaba si esto era posible en C++.Posible tener funciones anónimas de C++ con boost?

Lo que me gustaría hacer es (esencialmente)

template<typename T> 
T DoSomething(T one, function<T(T)> dosomething) 
{ 
    return one + dosomething(5); 
} 

void GetMyVal(...) 
{ 
    DoSomething<int>(1, /*anonymous func here*/) 
} 

Este ejemplo es muy, muy simplificada de lo que tengo que hacer. En C#, haría p => p * 5. Sé que esto es fácil con C++ 0x, pero no puedo usar eso. Siento que debería ser capaz de hacerlo con boost :: lambda, o una compilación de la función boost :: bind and boost :: con marcadores de posición, pero parece que no puedo hacer que funcione. Esto puede no ser posible y eso también está bien, pero por favor responda si no es posible. Gracias.

EDITAR: Ok, parece que el caso simple de un int funciona bien, ¿qué tal una estructura más complicada? Por lo tanto, vamos a tratar

struct NumHolder 
{ 
    int x; 
} 

template<typename T> 
T DoSomething(T one, function<T(NumHolder)> dosomething) 
{ 
    NumHolder temp; 
    temp = 5 
    return one + dosomething(temp); 
} 

void GetMyVal(...) 
{ 
    DoSomething<int>(1, /*anonymous func here*/) 
} 

Aquí mi C# sería la expresión en la línea de p => p.temp * 5. ¿Es esto posible hacerlo en C++ con impulso?

EDIT 2: Bien, ahora solo tengo curiosidad: D ¿Cómo puedo llamar a una función dentro de la expresión lambda? Entonces, si tenemos

int ChangeVal(int mult) 
{ 
    return mult*5; 
} 

struct NumHolder 
{ 
    int x; 
} 

template<typename T> 
T DoSomething(T one, function<T(NumHolder)> dosomething) 
{ 
    NumHolder temp; 
    temp = 5 
    return one + dosomething(temp); 
} 

void GetMyVal(...) 
{ 
    DoSomething<int>(1, /*anonymous func here*/) 
} 

En C# podría llamar a p => ChangeVal (p). ¿Cuál sería la sintaxis para esto con las expresiones C++ lambda?

+1

¿Es "mucho, mucho más fácil" guardar 5 líneas de declarar functor? – ima

+0

@ima: esta es la versión realmente simple de lo que tengo que hacer. de lo contrario, tengo docenas de funtores. En este caso, es mucho más fácil, simplemente no sabía la sintaxis – Steve

+1

No es sintaxis, se trata de plantillas enredadas que intentan implementar una gramática personalizada encima de C++. Es posible, pero me cuesta imaginar una situación en la que ahorrar algunas líneas de código valga ese precio. Tenga compasión por un tipo pobre manteniendo su código uno o dos años después ... – ima

Respuesta

5

Como Anders señala en su respuesta, boost :: lambda puede ser útil, pero el código puede ser difícil de leer en algunos casos. Por lo tanto, depende de lo que quiera hacer en su función anónima.

Para el caso simple como la p => p * 5 usted menciona en su pregunta, me parece que el uso de lambda o se unen sería razonable, sin embargo:

DoSomething(1, _1 * 5); 

Editar: Su segundo ejemplo impacta un área en la sintaxis se vuelve rápidamente detallado: acceso de miembros (datos o funciones). Debido a que el operador "punto" no puede ser sobrecargado en C++, usted tiene que utilizar una expresión se unen para conseguir la "x" de la discusión:

DoSomething(1, bind(&NumHolder::x, _1) * 5); 

o, con Boost.Lambda, utilice la sobrecarga -> * operador:

DoSomething(1, &_1->* &NumHolder::x * 5); 

Edición 2: bien, una vez más :) En su última pregunta, usted escribe que en C#, se escribiría p => ChangeVal(p), pero el código anterior muestra un ChangeVal tomando un int, no un NumHolder, por lo que no está claro a qué te refieres.

Suponiendo que ChangeVal toma un int y que desea que la función anónima para hacer el equivalente de ChangeVal(the_arg.x), que escribiría esto con Boost.Lambda:

DoSomething(1, bind(&ChangeVal, &_1->*&NumHolder::x)); 

o esto con Boost.Bind (trabaja con Lambda también):

DoSomething(1, bind(&ChangeVal, bind(&NumHolder::x, _1)); 
+0

gracias, ¿es posible usar esto con estructuras un poco más complicadas? He actualizado mi pregunta con un ejemplo – Steve

+0

¿Es posible llamar a una función desde dentro de la lambda? Pregunta actualizada con un ejemplo. – Steve

+0

funciona la versión de enlace de la última, la versión lambda da un error acerca de la conversión del controlador – Steve

2

No, no es posible hacer de una manera simple. boost :: lambda puede ayudar, pero en mi opinión, el código es tan difícil de leer cuando lo uso, así que lo evitaría.

Creo que el equivalente a C# p=>p*5 sería _1*5, pero solo lo he visto brevemente, así que no estoy seguro. Para cosas simples, funciona, pero tan pronto como necesite estructuras de control tendrá que usar otro conjunto de estructuras de control basadas funcionalmente, en lugar de imperativas. Encontré esto tan diferente del código C++ normal que decidí por mí mismo que no vale la pena usarlo, ya que hace que el código sea tan difícil de leer para los demás.

+0

¿sabe cómo hacerlo en impulsar lambda? – Steve

0

boost no extiende la sintaxis de C++. no hay funciones anónimas en C++.

+1

Sé que en realidad no hay funciones en C++. Me preguntaba si el impulso tenía una forma de fingirlo – Steve

Cuestiones relacionadas