Hello!
Je suis en train d'essayer de débugger l'application QtopiaMail de QtMoko qui n'arrive pas à lire les mails qui contiennent plusieurs parties dans leur message (une partie html et une partie txt par exemple).
Je m'y connais peu en C++, mais j'ai réussi à déterminer depuis quelle fonction sont crées les messages, la voici :
/*!
Returns the QMailMessage defined by a QMailMessageId \a id from
the message store.
*/
QMailMessage QMailStore::message(const QMailMessageId& id) const
{
// Resolve from overloaded member functions:
AttemptResult (QMailStore::*func)(const QMailMessageId&, QMailMessage*, MailStoreReadLock&) const = &QMailStore::attemptMessage;
QMailMessage msg;
repeatedly<ReadAccess>(bind(func, this, cref(id), &msg), "message(id)");
return msg;
}
On a donc QMailMessage la classe qui définit un message, QMailStore la classe qui permet d'enregistrer un message reçu et de le restaurer (justement avec cette fonction).
AttemptResult est un enum privé de QMailStore :
enum AttemptResult { Success = 0, Failure, DatabaseFailure };
repeatedly est une méthode privée de QMailStore définie ainsi, qui tente plusieurs fois de se connecter à la base de donnée :
bool repeatedly(FunctionType func, const QString &description) const;
Je voulais vous demander de l'aide pour comprendre ce que fait la ligne qui commence par AttemptResult dans le premier bout de code cité.
Est-ce que c'est bien la définition locale d'un pointeur de fonction qui prends trois arguments et qui pointe sur l'adresse de la fonction attemptMessage ?
Si c'est bien ça, je me demande également comment le compilateur c++ sait de quelle méthode attemptMessage il faut retrouver l'adresse, puisque cette méthode est définie de deux manière avec une première fois 3 arguments et la seconde fois 4 arguments. Est-ce qu'il le sait grâce à la définition du pointeur de fonction qui utilise justement 3 arguments ? Ça serait magique :D
Merci pour votre aide !
# Re: Aide sur du code C++ dans Qtopia
Posté par Gof (site web personnel) . Évalué à 6. Dernière modification le 26 février 2014 à 15:37.
Presque.
C'est la définition locale d'un pointeur vers une fonction membre qui prends trois argument et qui pointe vers QMailStore::attemptMessage.
Vu que tu assignes vers un un pointeur qui a 3 arguments, il sait quelle overload choisir.
Juste du C++ :-)
[^] # Re: Aide sur du code C++ dans Qtopia
Posté par Adrien Dorsaz (site web personnel, Mastodon) . Évalué à 1.
Merci beaucoup pour ta réponse claire et rapide :)
# Quand sait-on qu'on est passé du côté obscur de la Force?
Posté par arnaudus . Évalué à 2.
Je n'ai pas assez d'expérience en C++ pour savoir si le code cité est un exemple de «ceinture noire C++ 18ème dan», ou bien de l'obfuscation. On a quand même, en trois lignes de code,
1) Un pointeur de fonction interne overloadée et polymorphe, qui prend pour argument une ref constante, un pointeur, et une ref non constante, le tout vers des classes maisons—au passage, est-ce que la fonction attemptMessage est statique?
2) un appel à la fonction "repeatedly" avec de la STL hardcore, avec au passage l'argument MailStoreReadLock& que je ne vois pas (peut-être est-il fourni par défaut dans QMailStore::attemptMessage?)
Est-ce ce qu'il n'est vraiment pas spossible de faire tout ça plus simplement?
[^] # Re: Quand sait-on qu'on est passé du côté obscur de la Force?
Posté par Gof (site web personnel) . Évalué à 3.
Ce qui aurais été bien aurais été de pouvoir utilisé
attemptMessage
dans bind directement comme ça:Mais ça ne marche pas car
attemptMessage
est overloadé et donc il faut faire un case explicite vers le bon type pour résoudre quelle overload on prends. Par example, ce qui est fait dans le code original.Si c'est possible, en utilisant C++11. Avec une fonction lambda, on peu se passer de
bind
:[^] # Re: Quand sait-on qu'on est passé du côté obscur de la Force?
Posté par arnaudus . Évalué à 2.
Huhu, ça veut dire que le fait d'overloader une function quelque part peut péter le code à l'endroit qui appelle la fonction quand on utilise bind? Ça ressemble à un argument très fort contre l'utilisation de bind, non? Comment peut-on savoir a priori si la fonction qu'on bind est overloadée ou pas, et si on a la garantie qu'elle ne le sera jamais? Si je n'ai pas compris de travers,
peut marcher pendant des années, jusqu'au jour ou quelqu'un overloadera externalfunc? Ça me semble super bugogène ce truc, non?
[^] # Re: Quand sait-on qu'on est passé du côté obscur de la Force?
Posté par Gof (site web personnel) . Évalué à 2.
Oui exactement.
Ajouter des overload n'est pas compatible source.
Autre exemple:
Si je rajoute un overload je peux avoir des erreur. (si on rajoute
func(Bar*)
on a un appel ambigu (erreur de compilation), si on rajoutefunc(int)
une autre fonction est appelée (possible bug))[^] # Re: Quand sait-on qu'on est passé du côté obscur de la Force?
Posté par arnaudus . Évalué à 2.
Ah oui, moi j'étais juste resté sur les problèmes de cast automatique (style void func(double) qui peut être appelée func(3) ou func(3.0) sans problème, jusqu'au jour où elle est overloadée en void func(int)), qui ne posent problème que si le code est crade.
Je ne connais rien aux contraintes des compilos et des problèmes de cohérence des langages, mais il ne serait pas plus sain d'avoir un mot clé, je ne sais pas «nooverload», pour justement garantir à l'utilisateur que l'API est stable en terme d'overload, et qu'il peut faire des pointeurs de fonction de manière stable?
[^] # Re: Quand sait-on qu'on est passé du côté obscur de la Force?
Posté par Gof (site web personnel) . Évalué à 2.
Tu peux rajouter dans ton .h
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.