Templates et pointeurs de fonctions membres? - C++ - Programmation
Marsh Posté le 08-11-2004 à 23:29:32
et si tu nous donnais le code de ta classe composant (methode addActionListener) ?
Marsh Posté le 08-11-2004 à 23:55:48
oui, désolé,
Code :
|
Marsh Posté le 09-11-2004 à 00:00:50
moi je comprends pas ce que tu fais, ni où est le problème. Alors je te dirais tout simplement de tout virer.
Fais une classe template<typename Functor>
un membre Functor initialisé dans le constructeur
dans ta actionPerformed, tu fais un gros this->func(a, b, c)
et tu rajoutes un sucre syntaxique : une fonction qui crée les instances pour faire marcher la déduction de type
Marsh Posté le 09-11-2004 à 00:02:12
new ActionListener<ptr_TestFunc>(KeyEvent, buttonKeyEventActionPreformed
je vois pas comment ton truc ça peut marche, les différentes instances template d'ActionListener n'ont aucun lien de parenté, à part void*, tu peux rien en faire
Marsh Posté le 09-11-2004 à 00:08:42
ok, cool, en fait c'est plus ou moins ce que j'avais voulu faire.
Et ça m'arrange bien que tu me dises que y'ai moyen par ce que je commençais à me dire que je voyais vraiment pas comment faire autrement.
Mais donc ici dans mon ActionListener je devrai pouvoir chopper un pointeur de fonction membre de test, donc je capte pas pourquoi ça passe pas!
En fait c'est l'initialisation d'ActionListener qui plante:
Code :
|
Marsh Posté le 09-11-2004 à 00:11:20
ha merde je viens de voir le message au dessus
Marsh Posté le 09-11-2004 à 00:17:14
Taz a écrit : les différentes instances template d'ActionListener n'ont aucun lien de parenté, à part void*, tu peux rien en faire |
Ben j'ai pas trop compris en fait.
Je veux juste donné un pointeur de fonction membre d'object quelcquonque au constructeur d'ActionListener.
Mais il veut rien savoir...
Marsh Posté le 09-11-2004 à 01:04:08
c'est le addActionListener qui chie déjà, le reste je sais pas. c'est quoi le prototype de ton addActionListener ?
message d'erreur de compilation ?
toutes façons, ton code foire, tu manipules les pointeurs de fonctions n'importe comment. Apprends à les utilser, ou passe à une approche toute template.
Marsh Posté le 09-11-2004 à 01:17:59
Code :
|
une version typée pas template, ça serait ça.
Marsh Posté le 09-11-2004 à 01:19:12
pour le protoype :
void addActionListener(ptr_ActionListener );
et le message d'erreur :
error C2440: 'initializing' : cannot convert from 'class ActionListener<void (__thiscall Test::*)(int,int,int)> *' to 'class ActionListener<ptrMethode> *'
moi je me disais que c'était peu être à cause de
//pointeur de fonction d'ActionListener
template<class ptrMethode>
typedef ActionListener<ptrMethode> *ptr_ActionListener;
par ce que dans le message d'erreur le compilateur à pas l'aire d'interpreter le template?
Marsh Posté le 09-11-2004 à 09:04:52
je sais pas, je comprends rien à ta boue, t'as toujours pas filé un seul morceau de code complet.
Marsh Posté le 09-11-2004 à 09:50:16
on peut jouer à l'infini
Code :
|
pour pouvoir foutre dedans tous ce qui permet d'écrire 'x(i)' retournant 'void'.
À voir aussi chez boost (pour ne pas réinventer la roue)
http://www.boost.org/doc/html/function.html && http://www.boost.org/libs/bind/bind.html (fantastiques)
Pour rester plus classique et faire sauter les limitations de STL
http://www.boost.org/libs/bind/mem_fn.html (généralisation/correction de STL)
http://www.boost.org/libs/functional/index.html (généralisation/correction de STL)
Marsh Posté le 09-11-2004 à 10:18:38
En cadeau la définition des foncteurs généralisés d'A. Alexandrescu dans le livre "Modern C++ design".
L'auteur commence par définir un container de types calqué sur une liste façon Lisp, qu'il appelle Typelist. La version courte en est :
Code :
|
Dans la version longue, l'auteur définit tout un tas d'opérations sur les listes de types ainsi créées, comme le calcul de la longueur, un accès indexé, une opération de concaténation, de recherche, etc, opérations entièrement résolues à la compilation. Tout ça est pratique lorsqu'on veut définir des classes ou des fonctions avec un nombre variable de paramètres et des types indéterminés.
Ici on va se servir est l'accès indexé : on donne un index dans la liste et ça retourne le type correspondant:
Code :
|
Ainsi TypeAt<EntiersSignes, 2> retourne le type long int.
Maintenant venons-en aux foncteurs proprement dits :
Code :
|
Ca, c'est la version courte.
A l'utilisation, ça donne:
Code :
|
Marsh Posté le 09-11-2004 à 10:22:10
ouais ouais, boost::tuple pour la listequoi, boost toujours, boost vaincra !
explicit Functor(std::auto_ptr<Impl> spImpl);
par contre ça c'est bidon, vu le transfert de propriété
Marsh Posté le 09-11-2004 à 10:27:41
'fectivement, boost::tuple fait la même chose. D'ailleurs je ne serais pas étonné que boost::tuple soit inspiré de l'implémentation d'Alexandrescu dans Loki. C'est pourquoi la lib Loki d'Alexandrescu est un du coup un peu obsolète (c'est ce que j'ai mis dans mon CR de lecture dans le post ad'hoc), mais le bouquin permet de comprendre les choses.
Marsh Posté le 09-11-2004 à 10:31:33
bah Alexandrescu a rien inventé
et sans jamais l'avoir vu, tu très bien retrouvé ce genre de CRTP tout seul
Marsh Posté le 09-11-2004 à 11:21:55
Je suis en train de méditer sur vos post très instructifs (merci).
Je commence à y voir plus claire même si tout est loin d'être limpide.
Par exemple dans la version de Taz je ne comprend pas pourquoi ceci me donne ce message d'erreur?
error C2664: '__thiscall ActionListener<void (__thiscall Test::*)(int)>::ActionListener<void (__thiscall Test::*)(int)>(void (__thiscall Test::*const & )(int))' : cannot convert parameter 1 fro
m 'void (int)' to 'void (__thiscall Test::*const & )(int)'
C 'est comme si il considerait pas ma fonction "clickButtonActionPreformed" comme une fonction membre de Test
Code :
|
Marsh Posté le 09-11-2004 à 11:30:49
t'as rien compris ... &Test:: à la limite, mais ce n'est pas là l'usage qu'il faut en faire. Toute façon tu n'iras pas plus loin
T'es complètement perdu ... commence par voir comment on se sert d'un pointeur de fonction membre. Là t'en chie, alors je te file des pistes pour des cas génériques. Des liens pour tout planquer, ça passe comme une lettre à la poste, mais t'as pas l'air d'être intéressé par les liens ...
Marsh Posté le 09-11-2004 à 11:39:00
sisi, c juste que je pensais que le ... &Test:: était implicite et que ça pourrait marcher comme ça...
edit: ceci dis c'est vrai que je suis un peu paumé
Marsh Posté le 09-11-2004 à 11:51:57
ISO C++ interdit de prendre l'adress d'un membre de fonction non statique non qualifié ou entre parenthèses pour former un pointeur d'un membre de fonction. Utilisers «&Test::clickButtonActionPreformed»
Marsh Posté le 09-11-2004 à 14:50:58
Pour le deuxième exemple de Taz, mon compilo apprecie pas le push_back dans un vector :
'push_back' : cannot convert parameter 1 from 'class ActionListener<void (__thiscall Test::*)(int)> *' to 'const class boost::shared_ptr<struct `anonymous namespace'::ActionListene
rBase *> &'
J'avais cru comprendre que "boost:shared_ptr"
servais justement à eviter ça; mais apparement j'ai du encore me planter
(en passant je me demandais aussi pourquoi on utilisait un namespace anonyme pour ActionListenerBase?)
Marsh Posté le 09-11-2004 à 15:20:35
lol,
je compile avec visual par ce que j'ai commencé mon projet avec mais la prochaine étape (apres l'API) c'tai de porter le code sous g++...en attendant vous avez une idée d'une solution temporaire?
Au pire je pense pouvoir utiliser des poiteurs void à la place de références d'ActionListener... je vais tester ça ...
Marsh Posté le 09-11-2004 à 16:11:54
Si t'es sous VC7.1, en principe ça devrait passer, si t'es sous VC6, tu peux oublier Boost.
Marsh Posté le 09-11-2004 à 16:29:20
j'ai pas de bol aujourd'hui! J'ai VC6.
Mais merci c'est bon à savoir; si je ne trouve pas de solution je m'arrangerai pour me le procurer.
Marsh Posté le 09-11-2004 à 18:59:13
Et ma solution ? A défaut de Boost, tu peux quand même utiliser Loki, qui est quand même puissant, et qui a été porté sur VC6.
Marsh Posté le 09-11-2004 à 19:17:00
autant utiliser boost::function, c'est beaucoup meilleur à toutes nos sortes de hack.
Mais le problème, c'est la conception : si tu veux avoir une collection hétérogène d'objets callbacks, il faut que tu définies une interface, etc
Marsh Posté le 09-11-2004 à 19:21:48
Taz a écrit : autant utiliser boost::function, c'est beaucoup meilleur à toutes nos sortes de hack. |
Houlala, ton français s'améliore de jour en jour. Et il est sous VC6, on a dit.
Marsh Posté le 09-11-2004 à 19:55:33
c'est un peu fait exprès
et je sais pas, y a beaucoup de bricolage dans boost pour que ça marche avec VC6, faudrait voir à quand même essayer.
Moi je pense que t'es pas prêt pour les template. Commence à comprendre comment ça fonctionne les pointeurs de fonctions membres, fait du polymorphisme et voilà
Marsh Posté le 10-11-2004 à 00:46:51
Je vais suivre vos conseils... en tous cas j'ai appris pas mal de trucs...merci bien!
Ps : j'ai un solution qui m'a quand même l'aire pas trop mal; je ne donne finalement à mon controller que des pointeurs de fonctions membres d'actionListener (pas d'actionListener) et ai apparement plus besoin de template...je fait en suite une liste de pointeurs de fonctions membres d'ActionListener dans mon controller (et bon là j'ai encore un tit prob mais bon ça devrait être arrangeable)
A+
Marsh Posté le 10-11-2004 à 01:00:34
Je pense que ça ça devrait aller (avec quelques tests)... par contre je viens de passer une heure à pas comprendre pourquoi si j'ai un tableau static de pointeurs de fonctions membres d'ActionListener et que je l'initialise avec :
ActionListenerFunctor** Controller::actions(NULL);
il veut rien savoir alors que si je lui donne pas de valeur :
ActionListenerFunctor** Controller::actions;
il passe et le considère comme assigné à NULL mais bon je sors un peu du sujet du topic là ....
Marsh Posté le 10-11-2004 à 02:32:24
static ?
utilise l'initialisation par copie (= 0);
mais pourquoi ne pas utiliser un vector ?
Marsh Posté le 10-11-2004 à 05:27:41
Passe à VC7 en plus c'est gratuit:
http://msdn.microsoft.com/visualc/vctoolkit2003/
Marsh Posté le 10-11-2004 à 09:59:43
Quelques corrections dans le code que j'ai donné (attention, non testé, mais l'essentiel y est).
Marsh Posté le 10-11-2004 à 12:01:56
Ma première idée c'était de faire un
static std::vector<ActionListenerFunctor*> actions[NBR_ACTION_TYPES];
En fait chaque composants de l'API a une table dans laquelle il garde ses pointeurs et il passe au controller l'adress de l'entré de sa table pour pouvoir
gérer ses pointeur localement et changer de fonction puis effacer l'enter à la destruction du composant.
Mais j'ai un
error C2036: 'class std::vector<void (__thiscall ActionListener<_Ty>::**)(int,int,int),class std::allocator<void (__thiscall
ActionListener<_Ty>::**)(int,int,int)> > *' : unknown size
//d'ailleur malgré la doc je comprend pas trop cette erreur dans mon cas
et plus chiant ;
error C2662: 'push_back' : cannot convert 'this' pointer from 'class std::vector<void (__thiscall ActionListener<_Ty>::**)(int,int,int),class
std::allocator<void (__thiscall ActionListener<_Ty>::**)(int,int,int)> >' to 'class std::vector<_Ty,_A> &'
donc je m'était dis qu'un matrice ferait l'affaire ...
Mais évidement ça pouvais pas simplement marcher donc j'ai un problème d'allocation complètement débile; le compilateur ne détecte pas d'erreur mais dans le constructeur de Controller quand je fait :
Code :
|
si #define INIT_CONTOLLER_LENGHT 6 no prob
si #define INIT_CONTOLLER_LENGHT 7 no prob
si #define INIT_CONTOLLER_LENGHT 8 segmentation fault!?
0x049B1D30
0x049B1D38
0x049B1D40
0x049B1D48
0x049B1D50
0x049B1D58
0x049B1D60
0x00000038 plantage!
A croire que j'ai offensé le tout puissant par ce que là je vois pas le rapport !?
Sinon je met dans les pages de man qu'on peux pas avoir plus que 6compossants et que faudra attendre la version 2.0 mais je commence à fortement douter que mon projet révolutionne le monde de linformatique ce qui était pourtant ça vocation première...
LeGreg :
Passe à VC7 en plus c'est gratuit:
http://msdn.microsoft.com/visualc/vctoolkit2003/
Ha tiens je savais pas que c'était gratuit je vais tester ça!, mais d'abord finir 2-3 autres details (style aujourd'hui je dois absolument commenter (j'ai 3000lignes du proj sans un comment) ... sans doute le truc le plus chiant de la semaine d'ailleurs...)
Marsh Posté le 08-11-2004 à 23:17:05
Salut tout le monde;
Je me demandais si les templates pouvaient recevoir comme type des pointeurs de fonctions membres?
Si c'est le cas je ne comprend pas pourquoi ceci ne marche pas :
J'essaye en fait de donner un pointeur de fonction membre d'un objet quelconque à un ActionListener pour pouvoir ensuite donner à un controller des pointeurs de fonctions membres d'ActionListener
J'ai cru en être obligé de faire ça du fait que les types de fonctions membres d'objets différents sont incompatibles.
(si existe des types de pointeur de fonction membres dobjet « void » ça mintéresse aussi )
J'improvise c'est peu êter pas comme ça qu'il faut qu'il faut s'y prendre pour implémenter un controller mais bon si ce problème est résolut ça devrai marcher.
error C2440: 'initializing' : cannot convert from 'class ActionListener<void (__thiscall Test::*)(int,int,int)> *' to 'class ActionListener<ptrMethode> *'
Ce qui m'inquiète c'est que dans le message d'erreur le template est pas interprété.
Si vous avez des conseil, avis ils sont les bienvenu...
Message édité par peak le 08-11-2004 à 23:18:18