Comment boost bind fonctionne-t-il en coulisse?
-
02-07-2019 - |
Question
Sans passer beaucoup de temps à examiner le code source de boost, quelqu'un pourrait-il me donner un bref aperçu de la mise en œuvre de boost bind?
La solution
J'aime cette partie de la source 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
};
Vous dit presque tout ce que vous devez savoir, vraiment.
L'en-tête bind_template
se développe en une liste de définitions d'opérateur <)> incorporées. Par exemple, le plus simple:
result_type operator()()
{
list0 a;
BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
}
Nous pouvons voir que la macro BOOST_BIND_RETURN
se développe en return
à ce stade de sorte que la ligne ressemble davantage à return l_ (type ...)
.
La version à un paramètre est ici:
template<class A1> result_type operator()(A1 & a1)
{
list1<A1 &> a(a1);
BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
}
C'est assez similaire.
Les classes listN
sont des wrappers pour les listes de paramètres. Il y a beaucoup de magie profonde ici que je ne comprends pas trop, cependant. Ils ont également surchargé operator ()
qui appelle la mystérieuse fonction unwrap
. En ignorant certaines surcharges spécifiques du compilateur, cela ne fait pas beaucoup:
// 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();
}
La convention d'appellation semble être la suivante: F
est le type du paramètre de fonction pour bind
. R
est le type de retour. L
a tendance à être une liste de types de paramètres. Il y a aussi beaucoup de complications car il n’ya pas moins de neuf surcharges pour différents nombres de paramètres. Mieux vaut ne pas trop insister sur cela.
Autres conseils
À propos, si bind_t
est réduit et simplifié en incluant boost / bind / bind_template.hpp
, il devient plus facile à comprendre, comme suit:
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_;
};
Je pense que c'est une classe de modèle qui déclare une variable membre pour les arguments que vous voulez lier et une surcharge () pour le reste des arguments.