Как boost:: function и boost:: bind work

Мне не нравятся разбросанные по всему моему коду волшебные коробочки... как именно эти два класса работают, чтобы в принципе любая функция могла быть сопоставлена ​​объекту функции, даже если функция < > имеет совершенно другой параметр, установленный на один im переходит на 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); }
};

Это означает, что в вашем случае назначение функции boost:

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

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

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