std::bind
es para aplicación de función parcial .
Es decir, suponga que tiene un objeto de función f
que toma 3 argumentos:
f(a,b,c);
Desea un nuevo objeto de función que solo tome dos argumentos, definidos como:
g(a,b) := f(a, 4, b);
g
es una "aplicación parcial" de la función f
: el argumento del medio ya se ha especificado y quedan dos por recorrer.
Puedes usar std::bind
para obtener g
:
auto g = bind(f, _1, 4, _2);
Esto es más conciso que escribir una clase de functor para hacerlo.
Hay más ejemplos en el artículo al que se vincula. Por lo general, lo usa cuando necesita pasar un functor a algún algoritmo. Tiene una función o functor que casi hace el trabajo que desea, pero es más configurable (es decir, tiene más parámetros) que el algoritmo. Por lo tanto, vincula los argumentos a algunos de los parámetros y deja el resto para que el algoritmo complete:
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));
Aquí, pow
toma dos parámetros y puede elevar a cualquier potencia, pero todo lo que nos importa es elevar a la potencia de 7.
Como uso ocasional que no es una aplicación de función parcial, bind
también puede reordenar los argumentos a una función:
auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);
No recomiendo usarlo solo porque no le gusta la API, pero tiene posibles usos prácticos, por ejemplo, porque:
not2(bind(less<T>, _2, _1));
es una función menor o igual (suponiendo un orden total, bla, bla). Este ejemplo normalmente no es necesario ya que ya existe un std::less_equal
(usa el <=
operador en lugar de hacerlo <
, por lo que si no son consistentes, es posible que necesite esto, y que también deba visitar al autor de la clase con un clic de búsqueda). Sin embargo, es el tipo de transformación que surge si está utilizando un estilo funcional de programación.
myThread=boost::thread(boost::bind(&MyClass::threadMain, this))
std::function
?pow
ejemplo no se compila. Comopow
es una función sobrecargada, debe especificar manualmente qué sobrecarga. El enlace no puede dejar que sea deducido por la persona que llama del functor resultante. Por ejemplostd::transform(vec.begin(), vec.end(), out.begin(), std::bind((double (*)(double, int))std::pow, _1, 7));
std::bind
viene junto con elthis
uso como el segundo argumento. ¿Puedes por favor elaborar este caso de uso?std::placeholders::_1
. Me llevó un tiempo descubrir por qué esto no se estaba compilando.Uno de los principales usos de std :: function y std :: bind es como punteros de función más generelizados. Puede usarlo para implementar el mecanismo de devolución de llamada. Uno de los escenarios populares es que tiene alguna función que llevará mucho tiempo ejecutar, pero no desea esperar a que regrese, entonces puede ejecutar esa función en un hilo separado y darle un puntero de función que lo hará devolución de llamada después de que se complete.
Aquí hay un código de muestra sobre cómo usar esto:
fuente
std :: bind fue votado en la biblioteca después de la propuesta para incluir boost bind, principalmente es una especialización de función parcial en la que puede corregir algunos parámetros y cambiar otros sobre la marcha. Ahora esta es la forma de biblioteca de hacer lambdas en C ++. Como respondió Steve Jessop
Ahora que C ++ 11 admite funciones lambda, ya no siento ninguna tentación de usar std :: bind. Prefiero usar curry (especialización parcial) con la función de lenguaje que con la función de biblioteca.
Los objetos std :: function son funciones polimórficas. La idea básica es poder hacer referencia a todos los objetos invocables indistintamente.
Le señalaría estos dos enlaces para más detalles:
Funciones de Lambda en C ++ 11: http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8
Entidad invocable en C ++: http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
fuente
std::bind
nunca existió sin lambdas: ambas características se introdujeron en C ++ 11. Tuvimosbind1st
ybind2nd
que eran versiones demacradas de C ++ 11 bind.Lo usé hace mucho tiempo para crear un grupo de subprocesos de complementos en C ++; Como la función estaba tomando tres parámetros, puedes escribir así
Supongamos que su método tiene la firma:
Para crear un objeto de función para vincular los tres parámetros, puede hacer así
Ahora, para vincular los parámetros, tenemos que escribir una función de carpeta. Entonces, aquí va:
Y, una función auxiliar para usar la clase binder3 - bind3:
y aquí nosotros como llamarlo
Nota: f3 (); llamará al método task1-> ThreeParameterTask (21,22,23);
Para más detalles sangrientos -> http://www.codeproject.com/Articles/26078/AC-Plug-in-ThreadPool-Design
fuente