gatorette | Taz a écrit :
c'est correcte. t.d est la fonction disp liée à l'instance t. On a ça dans plein de langage comme python par exemple. Je souligné juste que l'intérêt, c'est de pouvoir manipuler (t.d) comme un objet indépendant et en faire ce qu'on veut.
|
OK... sinon j'ai essayé de faire ça en utilisant que la STL mais je n'ai pas réussi. Voici ce que j'ai fait jusqu'à présent :
Code :
- #include <iostream>
- #include <functional>
- using namespace std;
- class toto
- {
- public:
- toto(bool b)
- : d_(bind1st(mem_fun(&toto::disp1),this))
- {
- if(!b)
- d_ = bind1st(mem_fun(&toto::disp2),this);
- }
- typedef binder1st<mem_fun1_t<void,toto,int> > D;
- D d_;
- private:
- void disp1(int) { cout << "disp_1" << endl; }
- void disp2(int) { cout << "disp_2" << endl; }
- };
- int main()
- {
- toto t(true);
- t.d_(5);
- return 0;
- }
|
Deux gros problèmes :
- J'ai été obligé de mettre un paramètre (int) à mes fonctions car sinon le bind1st (indispensable pour lier le this à la fonction) n'a pas assez d'arguments. En effet, il exécute une fonction "binaire" (mon mem_fun_t acceptant comme argument mon pointeur vers mon objet toto et le int que j'ai rajouté) en simulant une fonction "unaire". La solution serait-elle de refaire une classe bindsolearg qui permettrait de binder à la création de l'objet le seul argument de la fonction qui nous intéresse ?
- Comme un binder1st n'a pas de constructeur par défaut (contrairement à boost::function par exemple), il faut que je l'initialise à la construction. Or je suis obligé de mettre une fonction membre de toto (à cause du mem_fun_t) et mon toto n'est pas encore complètement initialisé. VC++ me met même un warning lors de la compilation mais le programme semble tourner.
-----------------
v2
Bon en écrivant le message j'ai réflechi un peu et voici une version qui corrige les deux problèmes évoqués ci-dessus :
Code :
- #include <iostream>
- #include <functional>
- using namespace std;
- template<typename Operation>
- class bindsolearg
- {
- public:
- typedef typename Operation::result_type result_type;
- bindsolearg()
- : op(0)
- { }
- bindsolearg(const Operation & _Func, const typename Operation::argument_type& _Arg)
- : op(_Func), val(_Arg)
- { }
- result_type operator()() const
- {
- op(val);
- }
- protected:
- Operation op;
- typedef typename Operation::argument_type value;
- value val;
- };
- template<class Operation, class Type>
- bindsolearg<Operation> bindarg(const Operation& _Func, const Type& _Arg)
- {
- return bindsolearg<Operation>(_Func,_Arg);
- }
- class toto
- {
- public:
- toto(bool b)
- {
- if(!b)
- d_ = bindarg(mem_fun(&toto::disp2),this);
- else
- d_ = bindarg(mem_fun(&toto::disp1),this);
- }
- typedef bindsolearg<mem_fun_t<void,toto> > D;
- D d_;
- public:
- void disp1() { cout << "disp_1" << endl; }
- void disp2() { cout << "disp_2" << endl; }
- };
- int main()
- {
- toto t(true);
- t.d_();
- return 0;
- }
|
Donc cette version fonctionne à peu près correctement. A priori le seul "petit" souci est que mon objet functor peut ne pas être initialsé (en utilisant le constructeur par défaut) et donc si on appelle la fonction ça plante misérablement. Dans un sens on peut arguer que si l'objet n'est pas initialisé c'est qu'il y a un défaut de conception mais la méthode utilisée dans boost::function (exception générée) est beaucoup plus propre et exploitable.
Bon au final je pense qu'on peut conclure que Boost est vraiment indispensable ! ---------------
each day I don't die is cheating
|