Closed nutsi closed 11 years ago
Voici ce que l'on a imaginé au niveau des signaux:
Object
contiendrait principalement 4 méthodes: connect
, disconnect
, emit
et sender
void connect(const std::string&, SLOT)
: connecte un nom de signal à un slot (pointeur sur fonction, sur méthode, ou objet callable)void disconnect(const std::string&, SLOT)
: déconnecte le slot du signalvoid emit(const std::string&, ...)
: émet un signal depuis un objet. Tous les slots connectés se voient appelésObject* sender()
: Depuis une méthode faisant office de slot, référence l'objet émetteur du signalEt le déroulement des opérations:
connect
stocke simplement le nom du signal, l'objet courant et le slot dans une entité globale (tableau, vector, liste, ça reste à définir)disconnect
supprime une entrée de cette entitéemit
construit un StockCallback
(à l'aide de bind
) à partir des slots stockés connectés au signal émis. L'émetteur, le receveur et le StockCallback
sont ensuite entreposés dans une stack pour la thread-poolbind
@entwanne : la question est comment on stocke le SLOT sans creer le StockCallback
, parceque bon je veux bien que l'on ne le cree seulement lors du emit
mais ca pose quelque soucis pour son stockage.
Il n'y a que cela qui me gene.
Pour le disconnect
le stockage du pointeur this associer au SLOT va largement simplifier la tache.
Effectivement, il faut réfléchir à ce problème, et trouver une solution qui permet toujours de passer des paramètres par la suite.
On peux permettre le bind sans parametre?
bind(&myFunc);
Et faire le passage des parametres lors de l'appel de operator()
mais on au revient a la problematique que j'evoquais dans le premier post.
Je pense qu'il faudrait une classe (StockSlot
?) qui masquerait 2 éléments: le type de l'objet (pointeur sur fonction, sur méthode, objet), et le type de retour (on l'ignore). Cette classe comporterait 7 méthodes bind
templatées (de 0 à 6 paramètres). Elle nous permettrait donc de stocker nos slots.
Puis leurs méthodes bind
appelleraient notre fonction bind
avec les bons paramètres, et retourneraient le StockCallable
.
Ou même, on considère qu'on ne peut que stocker des pointeurs sur méthode (le reste n'a pas de raisons d'être slots
).
Mais je viens de me rendre compte qu'on aura des problèmes pour mêler templates et virtual.
J'ai bien trouvé une solution, qui n'utilise même pas bind
, mais ça pique un peu: https://gist.github.com/entwanne/905a0dd4d2675a0780b2
Le problème, c'est que le compilateur ne peut exercer aucune vérification sur les types. Donc si on se plante dans un prototype, ça fait de la merde et on voit difficilement pourquoi.
J'avoue, on peux ce permettre d'assumer le fait que l'on ne peux avoir que des signals sur des Object*
et pas de fonctions dites "normales".
Ta methode est un peu classe que celle avec bind, mais elle fait son taf.
Du coup, bind deviendrait useless -> Oui et non, car on pourra toujours avoir a un moment donner besoin de faire un callback, ne serait-ce que pour le protocole.
compliqué ce topic, hé bé !
Bon, j'ai trouvé ! J'ai dû modifier quelques trucs, ce n'est pas encore propre, donc pas commit, mais voici les détails:
Value
se voit maintenant dotée d'une méthode void set(const T&)
TypeListN
gagnent des méthodes void setK(const PK&)
(pour tous les 1 ≤ K ≤ N
)Caller
hérite d'une classe ParamCaller
templatée uniquement sur la liste de types (et c'est maintenant cette dernière qui la stocke)ParamCaller
hérite d'une interface ICaller
ParamCaller
implémente des méthodes void setK(T)
qui appelle le setK
de la liste de typesHerited
des StockCallback
gagne une méthode virtuelle pure renvoyant un ICaller*
Subterfuge
implémente donc cette méthode pour renvoyer le Caller
stockéStockCallaback
en implémente une aussi, retournant directement celle de son Herited*
ICaller*
récupéré, il est possible, par un dynamic_cast
, d'en obtenir le ParamCaller*
correspondant (il suffit de spécifier les types de paramètres, qui seront connus lors de l'emit
)ParamCaller*
, on peut utiliser les méthodes setK
et donc modifier les paramètresEUREKA
Cette fois-ci, c'est la bonne ! Commit dans très peu de temps avec la solution complète.
Je close.
Je poste tout de même le lien wiki qui explique comment fonctionne bind
et comment l'utiliser: https://github.com/nutsi/ZIA/wiki/Bind
Pour le moment, nous avons un bind fonctionnel qui fait de la rétention de paramètres (attention donc a la durée de vie des dit paramètres).
Ca pose des problèmes :
Personnellement, ca ne me dérange pas. D'autant plus, qu'avec ce mecanisme on s'assure que l'appel a la fonction "binder", ne plantera pas (ces parametres existe quoi qu'il ce passe).