1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
// cas phi1 : foncteur classique
struct phi1
{
void operator()(noeud *const arbre, double v)
{ ... }
};
// cas phi2 : pointeur sur fonction
void phi2(noeud *const arbre, double v);
// cas phi3 et phi4 : fonctions membres d'une classe
class X
{
public:
static void phi3(noeud *const arbre, double v);
void phi4(noeud *const arbre, double v);
};
// cas phi5: fonction phi membre de la classe noeud
// requiert l'inclusion du header standard <functional>
class noeud
{
public:
// prototype court, car le premier paramètre est en fait l'instance de
// noeud qui sera utilisée pour this.
void phi5(double v);
};
// ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
// Le code ci-dessous est un peu compliqué pour un débutant. Il est
// utile dans le cas où l'on veut passer en paramètre à pricing() une
// fonction membre non statique d'une classe quelconque (le cas phi4).
// J'en dit plus un peu plus bas sur ce sujet très particulier.
// ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
template <class C>
struct phi_helper
{
private:
C* m_instance;
void (C::*m_membre)(noeud *const, double);
public:
phi_helper(C* c, void (C::*m)(noeud *const, double))
: m_instance(c)
, m_member(m)
{ }
void operator()(noeud *const arbre, double v)
{
(m_instance->*m_membre)(arbre, v);
}
};
template <class C>
phi_helper<C> make_phi_helper(C* c, void (C::*m)(noeud *const, double))
{
return phi_helper<C>(c, m);
}
// ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
// Fin du code compliqué
// ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
void test_pricing()
{
noeud n;
// construit un objet du type phi1. pricing l'appelera grâce à son
// opérateur ()
p.pricing(..., phi1(), ...);
// on peut tout simplement lui passer un pointeur sur une fonction
// ou un pointeur sur une fonction membre statique
p.pricing(..., phi2, ...);
p.pricing(..., X::phi3, ...);
// avec un peu de courage, on peut aussi lui passer une fonction
// membre d'une classe, mais il faut l'associer à une instance de
// cette classe. Il faut s'aider d'un objet intermédiaire pour transformer
// le couple (Classe, fonction membre non statique) en foncteur classique.
// malheureusement, le standard C++ ne fournit pas un tel type, donc on
// en a développé un nous-même - c'est la classe template phi_helper<>
// ci-dessus. Puisqu'on veut se simplifier l'écriture au maximum, on va éviter
// d'instancier de manière explicite cette classe, et on va passer par une
// fonction template (make_phi_helper<>()) qui va déduire toute seule un
// certain nombre de choses.
X x; // il faut définir une instance de X
p.pricing(..., make_phi_helper(&x, &x::phi4),...);
// encore plus fort, si la fonction phi à passer en paramètre est une
// méthode de la classe noeud. Dans ce cas, le foncteur évalué se comporte
// ainsi :
// phi(node, v) --> node->mbrfun(v)
p.pricing(..., std::mem_fun_1(&noeud::phi5), ...);
} |
Partager