Предоставляет ли C++ 11 делегаты?Делегат в C++ 11
Если нет, то какой лучший (самый эффективный) способ сделать что-то подобное на C++? Boost.Signals? FastDelegate? Что-то другое?
Предоставляет ли C++ 11 делегаты?Делегат в C++ 11
Если нет, то какой лучший (самый эффективный) способ сделать что-то подобное на C++? 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)
.
+1, или вы можете просто превратить C в функтор. –
@jk: Только иногда. Очевидно, что в этом случае вы могли бы, но у меня не было много классов в моем приложении, которые имеют только одну функцию-член :-) –
Механизм C всегда был указателем функции & baton (за исключением 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);
}
Этот вопрос не о C: механизм C доступен на C++, но это не делает его лучший вариант. –
Я много работаю с делегатами в .NET и считаю, что таким образом избавил бы меня от неприятностей на пути делегатов, чем наоборот. – Joshua
Вам не обязательно нужно ждать C++ 0x. Вы можете реализовать делегатов почти так же в текущем стандарте C++ 03. Вам просто нужно перегрузить оператор(), так как вы можете позвонить MyObjectFunctor functor; functor();
, а поскольку функтор является объектом, вы можете передать его как делегат/объект в функции;
Текущая версия STL определяет заголовок <algorithm>
, который предоставляет функции, готовые для использования с функторами/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);
}
. Что могут сделать делегаты - это возможность хранить, например, 'int A :: func1 (int, int)' или 'int B :: func2 (int, int)' в переменной (например, 'f'), поэтому что его можно назвать похожим на 'int v = f (a, 12, 34);' или 'int v2 = f (b, 42, 24);'. В вашем примере может быть вызван функтор, но он не может рассматриваться как абстракция типа функции 'void (int)'. –
Вам не нужен C++ 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));
bind1st, bind2nd, mem_fun и mem_fun_ref устарели в C++ 11. –
Хотя std::function
работает хорошо, я хотел бы отметить, это хороший кусок кода делегата, написанный here (в том числе, например, использование!). Следуя рекомендациям и ответам, вы можете прочитать все о том, как этот класс Delegate
построен и почему он может быть быстрее, чем std::function
.
Отметим также, что мой вопрос here для проблемы я столкнулся с ним на VS 2015.
Что случилось с указателями на функции? – alternative
Я не могу использовать его с помощью метода класса:/ – dot222
да, вы можете http: //www.parashift.com/C++ - faq-lite/pointers-to-members.html, но есть, вероятно, лучшие вещи для использования, например. Функции C++ не должны быть методами, или вы можете превратить класс в функтор –