Как Boost Bind работает за кулисами в целом? - PullRequest
31 голосов
/ 22 сентября 2008

Не тратя много времени на просмотр исходного кода boost, не мог бы кто-нибудь дать мне краткое изложение того, как реализовано boost bind?

Ответы [ 3 ]

24 голосов
/ 22 сентября 2008

Мне нравится этот источник bind:

template<class R, class F, class L> class bind_t
{
public:

    typedef bind_t this_type;

    bind_t(F f, L const & l): f_(f), l_(l) {}

#define BOOST_BIND_RETURN return
#include <boost/bind/bind_template.hpp>
#undef BOOST_BIND_RETURN

};

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

Заголовок bind_template расширяется до списка встроенных определений operator(). Например, самое простое:

result_type operator()()
{
    list0 a;
    BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
}

Мы можем видеть, что макрос BOOST_BIND_RETURN расширяется до return в этой точке, поэтому линия больше похожа на return l_(type...).

Версия с одним параметром находится здесь:

template<class A1> result_type operator()(A1 & a1)
{
    list1<A1 &> a(a1);
    BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
}

Это очень похоже.

Классы listN являются оболочками для списков параметров. Здесь происходит много глубокой магии, которую я не очень понимаю. Они также перегружены operator(), вызывающим загадочную функцию unwrap. Не обращая внимания на некоторые специфичные для компилятора перегрузки, он ничего не делает:

// unwrap

template<class F> inline F & unwrap(F * f, long)
{
    return *f;
}

template<class F> inline F & unwrap(reference_wrapper<F> * f, int)
{
    return f->get();
}

template<class F> inline F & unwrap(reference_wrapper<F> const * f, int)
{
    return f->get();
}

Соглашение о присвоении имен выглядит так: F - это тип параметра функции для bind. R - это тип возвращаемого значения. L имеет тенденцию быть списком типов параметров. Есть также много сложностей, потому что существует не менее девяти перегрузок для различного числа параметров. Лучше не останавливаться на этом слишком много.

2 голосов
/ 03 декабря 2009

Кстати, если bind_t свернуть и упростить, включив boost/bind/bind_template.hpp, становится легче понять, как показано ниже:

template<class R, class F, class L> 
class bind_t
{
    public:

        typedef bind_t this_type;

        bind_t(F f, L const & l): f_(f), l_(l) {}

        typedef typename result_traits<R, F>::type result_type;
        ...
        template<class A1> 
            result_type operator()(A1 & a1)
            {
                list1<A1 &> a(a1);
                return l_(type<result_type>(), f_, a, 0);
            }
    private:
        F f_;
        L l_;

};
0 голосов
/ 22 сентября 2008

Я думаю, это шаблонный класс, который объявляет переменную-член для аргументов, которые вы хотите связать, и перегрузку () для остальных аргументов.

...