Как boost::function и boost::bind работают

Мне не нравится, когда магические блоки разбросаны по всему коду... как именно работают эти два класса, чтобы позволить в принципе любой функции отображаться на объект функции, даже если функция<> имеет совершенно другой параметр, установленный на тот, который я передаю в boost::bind

Он даже работает с различными соглашениями о вызовах (т.е. __thiscall под VC, но обычно "нормальные" функции __cdecl или же __stdcall для тех, которые должны быть совместимы с C.

1 ответ

Решение

boost::function позволяет что-нибудь с operator() с правильной сигнатурой для привязки в качестве параметра, и результат вашей привязки может быть вызван с параметром intтак что это может быть связано с function<void(int)>,

Вот как это работает (это описание относится так же для std::function):

boost::bind(&klass::member, instance, 0, _1) возвращает объект, подобный этому

struct unspecified_type
{
  ... some members ...
  return_type operator()(int i) const { return instance->*&klass::member(0, i);
}

где return_type а также int выведены из подписи klass::memberи указатель на функцию и связанный параметр на самом деле хранятся в объекте, но это не важно

Сейчас, boost::function не выполняет никакой проверки типов: он возьмет любой объект и любую подпись, указанную вами в параметре шаблона, и создаст объект, который вызывается в соответствии с вашей подписью и вызывает объект. Если это невозможно, это ошибка компиляции.

boost::function на самом деле такой объект:

template <class Sig>
class function
{
  function_impl<Sig>* f;
public:
  return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};

где return_type а также argument_type извлечены из Sig, а также f динамически размещается в куче. Это необходимо для того, чтобы совершенно не связанные объекты с различными размерами связывались с boost::function,

function_impl это просто абстрактный класс

template <class Sig>
class function_impl
{
public:
  virtual return_type operator()(argument_type arg0) const=0;
};

Класс, который выполняет всю работу, является конкретным классом, полученным из boost::function, Существует один для каждого типа объекта, который вы назначаете boost::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); }
};

В вашем случае это означает назначение функции повышения:

  1. создает экземпляр типа function_impl_concrete<void(int), unspecified_type> (это время компиляции, конечно)
  2. создает новый объект этого типа в куче
  3. назначает этот объект f члену boost::function

Когда вы вызываете объект функции, он вызывает виртуальную функцию своего объекта реализации, который направит вызов вашей исходной функции.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Обратите внимание, что имена в этом объяснении специально составлены. Любое сходство с реальными людьми или персонажами... вы это знаете. Цель состояла в том, чтобы проиллюстрировать принципы.

Другие вопросы по тегам