boost::function
permite que cualquier cosa con una operator()
con la firma correcta se vincule como parámetro, y el resultado de su vinculación se puede llamar con un parámetro int
, por lo que se puede vincular a function<void(int)>
.
Así es como funciona (esta descripción se aplica por igual std::function
):
boost::bind(&klass::member, instance, 0, _1)
devuelve un objeto como este
struct unspecified_type
{
... some members ...
return_type operator()(int i) const { return instance->*&klass::member(0, i);
}
donde return_type
y int
se infieren de la firma de klass::member
, y el puntero de la función y el parámetro vinculado se almacenan de hecho en el objeto, pero eso no es importante
Ahora, boost::function
no realiza ninguna verificación de tipo: tomará cualquier objeto y cualquier firma que proporciones en su parámetro de plantilla, y creará un objeto que se pueda llamar de acuerdo con tu firma y llamará al objeto. Si eso es imposible, es un error de compilación.
boost::function
es en realidad un objeto como este:
template <class Sig>
class function
{
function_impl<Sig>* f;
public:
return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};
donde el return_type
y argument_type
se extraen de Sig
, y f
se asigna dinámicamente en el montón. Eso es necesario para permitir que se unan objetos completamente no relacionados con diferentes tamaños boost::function
.
function_impl
es solo una clase abstracta
template <class Sig>
class function_impl
{
public:
virtual return_type operator()(argument_type arg0) const=0;
};
La clase que hace todo el trabajo, es una clase concreta derivada de boost::function
. Hay uno para cada tipo de objeto que asigneboost::function
template <class Sig, class Object>
class function_impl_concrete : public function_impl<Sig>
{
Object o
public:
virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); }
};
Eso significa en su caso, la asignación para impulsar la función:
- instancia un tipo
function_impl_concrete<void(int), unspecified_type>
(eso es tiempo de compilación, por supuesto)
- crea un nuevo objeto de ese tipo en el montón
- asigna este objeto al miembro f de boost :: function
Cuando llama al objeto de función, llama a la función virtual de su objeto de implementación, que dirigirá la llamada a su función original.
DESCARGO DE RESPONSABILIDAD: Tenga en cuenta que los nombres en esta explicación se inventan deliberadamente. Cualquier parecido con personas o personajes reales ... lo sabes. El propósito era ilustrar los principios.