Con boost-bind, el boost-function resultante puede recibir más argumentos de los esperados. Conceptualmente:¿Está usando boost :: bind para pasar más argumentos de los esperados?
int func() { return 42; }
boost::function<int (int,int,int)> boundFunc = boost::bind(&func);
int answer = boundFunc(1,2,3);
En este caso, func()
recibe 1,2, y 3 en la pila, aunque su firma indica que no tiene argumentos.
Esto difiere de la utilización más típica de boost::bind
para partial application, donde los valores se fijan para ciertos objetos produciendo un boost::function
que toma menos argumentos pero suministra el número correcto de argumentos cuando se invoca el objeto unido.
El siguiente código funciona con ambos MSVC++ 2010 SP1. Esta es una forma reducida de publicar; el código original también funciona bajo g ++ 4.4 en Linux.
¿Está lo siguiente bien definido según el estándar C++?
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std;
void func1(int x) { std::cout << "func1(" << x << ")\n"; } // end func1()
void func0() { std::cout << "func0()\n"; } // end func0()
int main(int argc,char* argv[])
{
typedef boost::function<void (int)> OneArgFunc;
OneArgFunc oneArg = boost::bind(&func1,_1);
// here we bind a function that accepts no arguments
OneArgFunc zeroArg = boost::bind(&func0);
oneArg(42);
// here we invoke a function that takes no arguments
// with an argument.
zeroArg(42);
return 0;
} // end main()
entiendo por qué zeroArg(42)
obras: el argumento no utilizado se pone en la pila por la rutina de llamada y simplemente no accede a la rutina de llamada. Cuando la rutina llamada vuelve, la rutina de llamada limpia la pila. Como puso los argumentos en la pila, sabe cómo eliminarlos.
¿Va a cambiar a otra arquitectura o compilatorio c++ romper esto? ¿Romperá esto una optimización más agresiva?
Estoy buscando una declaración más sólida, ya sea de la documentación de Boost o del documento de Estándares. No he podido encontrar una posición inequívoca en ninguno de los dos.
Usando un depurador y mirando el conjunto y la pila, está claro que func
del primer ejemplo no recibe los valores 1,2, y 3: está correcto en ese frente. Lo mismo es cierto para func0
en el segundo ejemplo. Esto es cierto al menos para las implementaciones que estoy viendo, MSVC++ 2010SP1 y g ++ 4.4/Linux.
En cuanto a la documentación mencionada Boost, que no es tan clara como me gustaría que es seguro para pasar argumentos adicionales:
bind(f, _2, _1)(x, y); // f(y, x)
bind(g, _1, 9, _1)(x); // g(x, 9, x)
bind(g, _3, _3, _3)(x, y, z); // g(z, z, z)
bind(g, _1, _1, _1)(x, y, z); // g(x, x, x)
Tenga en cuenta que, en el último ejemplo, el objeto de función producida por
bind(g, _1, _1, _1)
no contiene referencias a ningún argumento más allá del primero, pero aún se puede usar con más de un argumento. Cualquier argumento adicional se ignora silenciosamente, al igual que el primer y el segundo argumento se ignoran en el tercer ejemplo. [El subrayado es mío.]
La declaración acerca de los argumentos adicionales que son ignorados no es tan inequívoca como me gustaría para convencerme de que esto es cierto en el caso general. Mirando TR1, es claro desde Sec 3.6.3 que un objeto invocable devuelto desde bind
se puede invocar con un número de argumentos diferente al esperado objeto.¿Es esa la mejor garantía disponible?
+1 para una primera pregunta perfecta. Te quiero un poco –