легкий буст :: bind - PullRequest
       26

легкий буст :: bind

5 голосов
/ 19 декабря 2008

Мне так надоело создание анти-паттерна pass-callback-data-as-void * -struct. Boost bind хорошо решает эту проблему, но это недопустимая зависимость. Какая легкая альтернатива? Как бы я сам написал это настолько просто, насколько это возможно?

Ответы [ 7 ]

17 голосов
/ 19 декабря 2008

Во-первых, я подвергаю сомнению ваше утверждение, что оно слишком тяжелое для вас.

Во-вторых, сверните свой собственный шаблон, если вам нужно контролировать поведение.

В-третьих, если вы боитесь свернуть свой собственный шаблон, я сомневаюсь в вашей способности судить, что boost::bind слишком тяжел для вас.

7 голосов
/ 19 декабря 2008

Посмотрите на быстрый делегат Дона Клагстона. Предположительно, это самый быстрый делегат, который вы можете найти на большинстве современных платформ (компилируется до двух инструкций по сборке.) Версия 1.4+ получает некоторую совместимость с Boost.Bind.

2 голосов
/ 19 декабря 2008

Boost.Function значительно улучшила производительность примерно до 1,34 при использовании вместе с boost :: bind. Если вы профилировали со старой надстройкой, возможно, сделайте это снова с более свежей версией. boost::function получил возможность сохранять небольшие функциональные объекты в небольшом буфере, выделенном в стеке, а не в куче (с использованием размещения new).

См. Это сообщение списка рассылки: http://lists.boost.org/Archives/boost/2006/01/98993.php.

2 голосов
/ 19 декабря 2008

Распространенной идиомой C ++ является использование функторов (то есть объектов, которые переопределяют operator ()). Дело в том, что вы используете один объект для инкапсуляции как кода, который необходимо вызвать, и данных, на которые будет воздействовать этот код. Независимо от того, выполняется ли функтор вручную или генерируется с помощью boost :: bind и / или , вероятно, не имеет большого значения для накладных расходов времени выполнения.

Так что вместо:

typedef void (*cb)(void*);
void funcThatNeedsCallback(cb thecallback, void *thedata) {
    // blah blah
    thecallback(thedata);
}

сделать:

template<typename T>
void funcThatNeedsCallback(T &thefunctor) {
    // blah blah
    thefunctor();
}

Тогда звонящий делает:

struct MyFunctor {
    int mydata1;
    char *mydata2;
    void operator()(void) {
        // do something with mydata1 and mydata2
    }
};

MyFunctor mf = { value1, value2 };
funcThatNeedsCallback(mf);

Очевидно, что если вы предпочитаете, вы можете сделать члены частными и передать их конструктору, а не использовать список инициализаторов.

Если вы беспокоитесь о шаблонах (например, если funcThatNeedsCallback содержит много кода, который дублируется), то используйте абстрактный класс для определения виртуального метода, который должен иметь параметр, и используйте этот метод в качестве обратного вызова:

class CallbackInterface {
    virtual void theCallback(void) = 0;
    virtual ~CallbackInterface() {} // just in case
};

void funcThatNeedsCallback(CallbackInterface &cb) {
    // blah blah
    cb.theCallback();
}
2 голосов
/ 19 декабря 2008

Я не знаком с boost: bind, но так ли это?

#include <iostream>

void foo (int const& x) {
    std::cout << "x = " << x << std::endl;
}

void bar (std::string const& s) {
    std::cout << "s = " << s << std::endl;
}

template<class T>
void relay (void (*f)(T const&), T const& a) {
    f(a);
}

int main (int argc, char *argv[])
{
    std::string msg("Hello World!");
    relay (foo, 1138);
    relay (bar, msg);
}

Выход -

x = 1138
s = Hello World!
1 голос
/ 22 января 2010

Люди, защищающие скорость boost :: binding, вероятно, никогда не писали торговые системы с низкой задержкой или высокоскоростные графические библиотеки.
Boost - хорошая библиотека общего назначения, а не оптимизированная по скорости. Некоторые библиотеки boost (по сравнению с настроенными реализациями) могут быть довольно медленными по сравнению.

Для функций / делегатов см. http://www.codeproject.com/KB/cpp/fastdelegate2.aspx для полезного сравнения.

Ciao.

1 голос
/ 19 декабря 2008

Существует libsigc ++ . Лицензия LGPL, но реализация - это то, что делает Boost.Signal (я читаю «слишком тяжелый», чтобы означать «установка всего Boost слишком тяжелая», а не «Boost.Signal слишком медленный»).

...