====== Зачем это нужно ====== Во многих современных языках существует понятие "делегата" - некоторой сущности, позволяющей косвенно вызвать тот или иной метод. Наиболее близкая аналогия в С++ - это указатель на функцию или член класса. Но каждый разработчик на С++, кто сталкивался с такого рода указателями, в итоге выясняет, что они - не полноценный аналог делегата. По двум причинам: - Указатель на функцию и указатель на член класса не могут быть преобразованы друг в друга. - Для доступа к члену класса по указателю обязательно требуется указатель на объект, относительно которого производится вызов. А по этому, если указатели на свободные функции или статические функции еще можно как-то рассматривать в качестве делегатов, то с указателями на члены класса все гозаздо сложнее. Для устранения этих проблем и был создан шаблонный класс boost::function (а точнее - набор шаблонных классов). Что это такое? По сути - boost::function (точнее, результат его инстанцирования) - это функтор (функциональный объект), к которому применим оператор "()" (вызова функции). А потому в исходный тексте программы вызов метода напрямую или через boost::function ничем не отличимы. В качестве аргументов шаблона boost::function принимает сигнатуру метода, который он будет "эмулировать". Например: boost::function foo1; // (соответствует методу с сигнатурой void foo1();) boost::function foo2; // соответствует методу // int foo2(int arg1, float arg2, SomeClass& arg3) // и т. д. А инициализироваться может либо указателем на соответствующий метод, либо другим функциональным объектом, который может быть вызван с указанными параметрами: void foo1(int a) {;} struct Foo1 { void operator() (int a) {;} } boost::function Delegate; //... Delegate = foo1; // ... Delegate(10); // будет реально вызван foo1(10) // ... // ... Delegate = Foo1(); // ... Delegate(10); // будет вызван Foo1::operator()(10); ====== Как это использовать ====== boost::function можно использовать: * Со свободными (глобальными) функциями. * С функциями-членами. * С функциональными объектами. Синтаксис объявления экземпляра boost::function не меняется. Аргументы, которые может принимать boost::function такие же, какие может принимать обычная функция. При этом (как и для обычной функции) можно перечислять как просто типы аргументов, так и типы с формальными именами параметров: // оба объявления равноценны boost::function f1; boost::function f2; Максимальное количество аргументов, которое может принимать boost::function зависит от реализации. Чаще всего - не больше 10. После объявления экземпляра boost::function его необходимо обязательно заполнить (проинициализировать). До этого момента экземпляр будет считаться "пустым" и при попытки применить к нему оператор вызова функции будет выброшено исключение bad_function_call. ===== Использование вместе со свободными функциями ===== Для использования boost::function совместно со свободными функциями достаточно проинициализировать объект адресом соответствующей функции: void foo(int, int) {;} boost::function f1; f1 = foo; // или f1 = &foo; ===== Использование вместе с функциями-членами ===== Используется также, как и со свободными функциями: class SomeClass { public: void foo(int, int) {;} } boost::function f1; f1 = &SomeClass::foo; Но использование такого функционального объекта требует передачи ему экземпляра класса, для которого должна быть вызвана функция: SomeClass obj; f1(&obj, 10); В случае необходимости передачи "чистого" функционального объекта ситуацию спасает использование [[doc:cpp:boost:bind|boost::bind]], или std::bind1st: SomeClass* obj = ...; f1 = boost::bind(&SomeClass::foo, obj, _1); //... f1(10); // эквивалентен вызову f1 из предыдущего примера Статические функции члены передаются в boost::function также, как и свободные функции. ===== Использование с функциональными объектами ===== Если для какого-то объекта можно применить оператор вызова функции, то он также, как и обычные функции, может быть использован для инициализации boost::function. Пример был приведен в предыдущем разделе, когда boost::function инициализировался функциональным объектом boost::bind. Поскольку функциональный объект в boost::function хранится по значению, то в случае необходимости передачи ссылки необходимо воспользоваться boost::ref: SomeFunctionObject foo; boost::function f1; f1 = boost::ref(foo); boost::function f2; f2(f1); В этом случае f1 и f2 будут использовать для работы один и тот же функциональный объект. ====== Недостатки ====== ====== Достоинства ====== Дополнительную информацию по использованию можно найти в оригинальной документации: http://www.boost.org/doc/html/function.html