Предоставляет ли С++ 11 делегаты?
Если нет, то какой лучший (самый эффективный) способ сделать что-то подобное на С++? Boost.Signals? FastDelegate? Что-то еще?
Предоставляет ли С++ 11 делегаты?
Если нет, то какой лучший (самый эффективный) способ сделать что-то подобное на С++? Boost.Signals? FastDelegate? Что-то еще?
Вы можете получить семантику, подобную делегату, используя bind
для привязки функции-члена к экземпляру класса:
#include <functional>
struct C
{
void Foo(int) { }
};
void Bar(std::function<void(int)> func)
{
func(42); // calls obj.Foo(42)
}
int main()
{
using namespace std::placeholders;
C obj;
Bar(std::bind(&C::Foo, obj, _1));
}
В этом примере Bar()
берет все, что имеет один параметр int
и возвращает void
.
В main()
мы привязываем указатель на функцию-член C::Foo
к экземпляру C
с именем obj
. Это дает нам объект, который можно вызвать с помощью одного параметра int
и который возвращает void
.
Мы вызываем Bar()
с этим объектом, а Bar()
выполняет вызов obj.Foo(42)
.
Вам не нужен С++ 0x. в <functional>
у вас есть bind1st
bind2nd
mem_fun
и mem_fun_ref
. У вас также есть Boost.Bind, который обобщает все вышеперечисленные функции (IIRC).
Переход из памяти...
vector<Foo> foo = makeVector();
vector<Foo*> foop = makeVectorP();
vector<Bar> bar1,bar2,bar3,bar4;
transform( foo.begin(), foo.end(), back_inserter( bar1 ), mem_fun_ref(&Foo::getBar) );
transform( foop.begin(), foop.end(), back_inserter( bar2 ), mem_fun(&Foo::getBar) );
transform( foo.begin(), foo.end(), back_inserter( bar3 ), bind1st(&bar_from_foo) );
transform( foo.begin(), foo.end(), back_inserter( bar4 ), boost::bind(&bar_from_foo, _1) );
Хотя std::function
работает красиво, я хотел бы отметить этот приятный фрагмент кода делегата, написанный здесь (включая пример использования!). Следуя рекомендациям и ответам, вы можете прочитать все о том, как этот класс Delegate
построен и почему он может быть быстрее, чем std::function
.
Обратите внимание также на мой вопрос здесь на проблему, с которой я столкнулся с ней на VS 2015.
Вам не обязательно ждать С++ 0x. Вы можете реализовать делегатов почти так же в текущем стандарте С++ 03.
Вам просто нужно перегрузить оператор(), чтобы вы могли вызвать MyObjectFunctor functor; functor();
, а поскольку функтор - это объект, вы можете передать его как делегат/объект в функции;
текущая версия STL определяет заголовок <algorithm>
, который предоставляет функции, готовые для использования с Functors/Lambdas/Delegates.
простой пример функтора.
struct FunctorDelegate
{
// as so to delegate as a function that takes an int input
void operator()(int)
{
// do what I want
}
};
int main()
{
//... do some stuffs with an std::vector<int> aRange;
FunctorDelegate functor;
std::for_each(aRange.begin(), arange.end(), functor);
}
Механизм C всегда был указателем функции и дубинкой (кроме qsort() и bsearch(), которые не принимали эстафету).
Таким образом, всегда можно передать объект класса в качестве дубинки.
например:.
class tp {
public:
tp() { n = 0; }
void m(int z) { printf("%d is %d\n", n++, z++); }
int n;
};
void higher_func(int *opx, int cnt, void *handler(int itm, void *baton), void *baton)
{
for (int i = 0; i < cnt; i++)
handler(opx[itm], baton);
}
/* You would need to provide this stub -- potentially templateable */
void translate_baton(int itm, void *baton) { ((tp *)baton)->m(itm); }
/* used like so: */
int main()
{
int array[7];
//...
tp cx;
higher_func(array, 7, translate_baton, &cx);
}