Делегат в C ++ 11 - PullRequest
       45

Делегат в C ++ 11

11 голосов
/ 02 сентября 2010

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

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

Ответы [ 5 ]

14 голосов
/ 02 сентября 2010

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

Вам не нужен с ++ 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) );
1 голос
/ 14 марта 2016

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

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

0 голосов
/ 02 сентября 2010

Вам не обязательно ждать C ++ 0x. Вы можете почти так же реализовать делегатов в текущем стандарте C ++ 03. Вам просто нужно перегрузить operator (), чтобы вы могли вызвать 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);
}
0 голосов
/ 02 сентября 2010

Механизм 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...