boost::function
permite que qualquer coisa com um operator()
com a assinatura correta seja vinculado como parâmetro, e o resultado de sua vinculação pode ser chamado com um parâmetro int
, para que possa ser vinculado function<void(int)>
.
É assim que funciona (esta descrição aplica-se igualmente a std::function
):
boost::bind(&klass::member, instance, 0, _1)
retorna um objeto como este
struct unspecified_type
{
... some members ...
return_type operator()(int i) const { return instance->*&klass::member(0, i);
}
em que return_type
e int
são inferidos da assinatura de klass::member
, e o ponteiro de função e o parâmetro vinculado são de fato armazenados no objeto, mas isso não é importante
Agora, boost::function
não faz nenhuma verificação de tipo: ele pegará qualquer objeto e qualquer assinatura que você fornecer em seu parâmetro de modelo e criará um objeto que pode ser chamado de acordo com sua assinatura e chamará o objeto. Se isso for impossível, é um erro de compilação.
boost::function
é na verdade um objeto como este:
template <class Sig>
class function
{
function_impl<Sig>* f;
public:
return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};
de onde return_type
e argument_type
são extraídos Sig
e f
são alocados dinamicamente no heap. Isso é necessário para permitir que objetos completamente não relacionados com tamanhos diferentes sejam vinculados boost::function
.
function_impl
é apenas uma classe abstrata
template <class Sig>
class function_impl
{
public:
virtual return_type operator()(argument_type arg0) const=0;
};
A classe que faz todo o trabalho é uma classe concreta derivada de boost::function
. Existe um para cada tipo de objeto que você atribuiboost::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); }
};
Isso significa, no seu caso, a atribuição para impulsionar a função:
- instancia um tipo
function_impl_concrete<void(int), unspecified_type>
(que é o tempo de compilação, é claro)
- cria um novo objeto desse tipo na pilha
- atribui este objeto ao membro f de boost :: function
Quando você chama o objeto de função, ele chama a função virtual de seu objeto de implementação, que direcionará a chamada para sua função original.
AVISO LEGAL: Observe que os nomes nesta explicação são deliberadamente inventados. Qualquer semelhança com pessoas ou personagens reais ... você sabe disso. O objetivo era ilustrar os princípios.