Делегировать на С++ 11

Предоставляет ли С++ 11 делегаты?

Если нет, то какой лучший (самый эффективный) способ сделать что-то подобное на С++? Boost.Signals? FastDelegate? Что-то еще?

Ответ 1

Вы можете получить семантику, подобную делегату, используя 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).

Ответ 2

Вам не нужен С++ 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) );

Ответ 3

Хотя std::function работает красиво, я хотел бы отметить этот приятный фрагмент кода делегата, написанный здесь (включая пример использования!). Следуя рекомендациям и ответам, вы можете прочитать все о том, как этот класс Delegate построен и почему он может быть быстрее, чем std::function.

Обратите внимание также на мой вопрос здесь на проблему, с которой я столкнулся с ней на VS 2015.

Ответ 4

Вам не обязательно ждать С++ 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);
}

Ответ 5

Механизм 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);
}