xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 2 janv. 2005 à 23:48
J'ai qd même ajouter une fonction membre "without_throw" avec un return par défaut qui effectivement ,'a que peu de sens.
Merci encore pour ton aide.
plus_plus_fab
Messages postés232Date d'inscriptionvendredi 9 janvier 2004StatutMembreDernière intervention 8 janvier 2005 2 janv. 2005 à 12:46
salut,
effectivement V1 n'apporte rien, et le pire (je me confesse), c'est que je n'en étais pas conscient !
La version 2 souffre d'un gros défaut : on ne peut pas appeler what() si l'exception ne dérive pas de std::exception. On perd donc le message d'erreur. De plus, si la classe d'exception possede d'autres informations accessibles avec d'autres méthodes que what(), c'est perdu aussi (qu'elle dérive de std::exception ou non). A abandonner donc.
Pour la version 3, ça me parait difficile de retourner qqchose de cohérent ... (il n'y a pas de return)
Finalement, je pense que ton code est bon tel qu'il est.
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 30 déc. 2004 à 23:41
Dans la V1, le try/catch n'apporte rien par rapport à l'original. La V2 peut effectivement répondre à un besoin spécifique : masquer toutes les exceptions (std ou pas).
// v2 :
on est sur que cette méthode ne déclenchera pas d'autres exceptions.
personellement, je ne définirais pas les classes d'exceptions à l'intérieur
des classes de call_back. Par contre, je les emballerai dans le meme
espace de nommage.
cette solution amene naturellemnt à faire hériter bad_instance, bad_method, bad_call_unexpected et bad_call, de bad_callback (par exemple), lui meme héritant de std::exception (comme c'est le cas).
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 29 déc. 2004 à 12:50
Bonjour,
L'ecriture des classes callback reste perfectible. Mais cela prend une tournure intéressante ! Merci pour tes conseils. ^_^
Cordialement,
X.
plus_plus_fab
Messages postés232Date d'inscriptionvendredi 9 janvier 2004StatutMembreDernière intervention 8 janvier 2005 28 déc. 2004 à 20:35
Salut,
pour les exceptions, je songe à une autre conception, faire 2 méthodes dans les t_callback*, une qui n'utilise pas les exceptions (operator()(...)), l'autre qui déclencherai des exceptions, et qui propagerai les exceptions pouvant intervenir dans la fonction appelée. C'est juste une idée ...
"A charge du developpeur soit de completer le throw par une exception standard ou de son cru"
Pourquoi pas une classe d' exception "de son cru" dérivant des exceptions standard ?
"L'appelle d'une fonction (par son pointeur) compte pour 90% dans le temps d'execution du test de callback dynamique."
Je pense qu'un bon optimiseur doit pouvoir éliminer ce code d'erreur, tout est facilement prévisible à la compilation ... Par contre, je ne suis pas sur de la résolution inline de la fonction appelée par l'intermédiaire d'un pointeur de fonction.
Avec ton main, il est intéressant de constater la différence de rapidité d'exécution entre la version const et la version non const (si on compile sans optimisations).
Sinon, ça fait plaisir de voir un programmeur sous w$ évoluant du coté clair :)
@+
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 28 déc. 2004 à 19:53
Au passage, l'execution de ce test (throw) influe tres peu sur le resultat en terme de performance. C'est pourtant du code en plus qui ne se retrouve pas dans les autres callbacks. L'appelle d'une fonction (par son pointeur) compte pour 90% dans le temps d'execution du test de callback dynamique.
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 28 déc. 2004 à 19:48
Remarque est tout a fait justifiée (encore une fois). A charge du developpeur soit de completer le throw par une exception standard ou de son cru, soit tout simplement de la supprimer (ou la traiter différemment)!
Dans l'état, le throw appelle terminate(). C'est un tout petit peu plus propre qu'un segfault (et le docteur watson qui s'en suit). L'idée y est... on peut faire mieux.
plus_plus_fab
Messages postés232Date d'inscriptionvendredi 9 janvier 2004StatutMembreDernière intervention 8 janvier 2005 28 déc. 2004 à 18:56
"Toutes mes excuses pour cet oubli impardonnable !"
Vous etes pardonné mon cher mais que ça ne se renouvelle pas :)
Cette ligne me parait bizarre ...
redéclenchement de quelle exception ?
if( _class_instance 0 && _method 0 ) throw;
il vaudrait mieux déclencher une exception, voire séparer les tests et en déclencher une différente suivant le cas. Ou bien enlever la méthode set et oter les parametres optionels dans le constructeur ? ça restreint un peu son utilisation d'accord ...
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 28 déc. 2004 à 14:01
Qualitativement, la différence de performance entre un appel direct et un appel par callback statique est négligeable.
Inversement entre un callback dynamique et un callback statique, la perte de temps semble considérable.
A méditer !
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 27 déc. 2004 à 23:13
3 const ajoutés. Toutes mes excuses pour cet oubli impardonnable !
plus_plus_fab
Messages postés232Date d'inscriptionvendredi 9 janvier 2004StatutMembreDernière intervention 8 janvier 2005 27 déc. 2004 à 22:39
const ici aussi :
t_callback_const( const t_class& c ) : _callback_class( c ) {}
plus_plus_fab
Messages postés232Date d'inscriptionvendredi 9 janvier 2004StatutMembreDernière intervention 8 janvier 2005 27 déc. 2004 à 22:37
pour les exceptions, tu veux pouvoir gérer une méthode genre :
void A::f(void)throw(std::bad_alloc) ? mis à part un catch(...) throw, je ne vois pas comment faire mieux.
"Je suis un peu étonné de ta dernière remarque. Peux-tu préciser ? Ca m'intéresse."
Désolé, rien d'intéressant, juste pour dire que j'ai déjà vu d'horribles programme s(inspiré des pointeurs de fonctions en C) qui utilisaient abusivement les pointeurs de fonctions membres, en détriment d'une conception objet cohérente. De la à la violer ? Je suis en train d'y réfléchir ...
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 27 déc. 2004 à 18:29
Dans mon exemple, les fonctions membres devraient effectivement être const. J'ai porté peu d'attention à leur écriture.
Pour les questions/observations, j'attendais aussi les exceptions... cela dit, je vais prendre en compte cette remarque et proposer le support des fonctions membres conts. A priori, cela oblige à définir deux classes distinctes "callback" très proches l'unes de l'autres. Je vais y réfléchir !
Je suis un peu étonné de ta dernière remarque. Peux-tu préciser ? Ca m'intéresse.
Cordialement,
X.
plus_plus_fab
Messages postés232Date d'inscriptionvendredi 9 janvier 2004StatutMembreDernière intervention 8 janvier 2005 27 déc. 2004 à 18:15
salut,
Tu attends surement qu'on te pose la question : et la "constness" ?
alors, je te la pose :)
Mise à part que les fonctions membres des exemples doivent etre déclarées const, aucune remarque sur le code, j'aime bien.
Mais je considère les procédés de ce genre comme des hacks à n'utiliser que dans des cas bien spécifiques.
xterminhate
Messages postés371Date d'inscriptiondimanche 4 janvier 2004StatutMembreDernière intervention23 septembre 2009 27 déc. 2004 à 08:56
Ce code compile et s'execute avec succes avec les compilateurs suivans : MinGW, Cygwin, et MS .Net 2003 (VC7).
A moins de vouloir à tout prix utiliser les MFC dans tes programmes, tu devrais changer de compilateur parce qu'il ne sait pas faire de C++ correctement (en particulier les écritures à base de template).
Je ne peux donc rien faire pour tes erreurs, désolé.
Cordialement,
X.
jerrol
Messages postés11Date d'inscriptionmercredi 25 décembre 2002StatutMembreDernière intervention29 décembre 2004 27 déc. 2004 à 07:38
Salut !
J'ai compilé avec Visual C++6, et j'ai les erreurs suivantes :
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(17) : error C2973: 't_callback' : invalid template argument 'fm'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(25) : see declaration of 't_callback'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(88) : see reference to class template instantiation 't_callback<struct A,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,
int const &,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall A::fa(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(103) : see reference to class template instantiation 'X<struct A,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
__thiscall A::fa(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(17) : error C2973: 't_callback' : invalid template argument 'fm'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(25) : see declaration of 't_callback'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(88) : see reference to class template instantiation 't_callback<struct B,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,
int const &,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall B::fb(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(104) : see reference to class template instantiation 'X<struct B,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
__thiscall B::fb(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(107) : warning C4508: 'main' : function should return a value; 'void' return type assumed
Error executing cl.exe.
testconsole.exe - 2 error(s), 1 warning(s)
Faut-il configurer le projet d'une façon spécifique ?
2 janv. 2005 à 23:48
Merci encore pour ton aide.
2 janv. 2005 à 12:46
effectivement V1 n'apporte rien, et le pire (je me confesse), c'est que je n'en étais pas conscient !
La version 2 souffre d'un gros défaut : on ne peut pas appeler what() si l'exception ne dérive pas de std::exception. On perd donc le message d'erreur. De plus, si la classe d'exception possede d'autres informations accessibles avec d'autres méthodes que what(), c'est perdu aussi (qu'elle dérive de std::exception ou non). A abandonner donc.
Pour la version 3, ça me parait difficile de retourner qqchose de cohérent ... (il n'y a pas de return)
Finalement, je pense que ton code est bon tel qu'il est.
30 déc. 2004 à 23:41
Je proposerait égallement une V3 "bete&mechante" :
inline t_return call_wo_throw( t_argument parameter ) throw ()
{
try
{
return ( _class_instance->*_method )( parameter );
}
catch(...)
{
// rien
}
}
29 déc. 2004 à 22:25
Je te propose 2 solutions pour propager les exceptions :
// v1 :
inline t_return call( t_argument parameter )
{
if( _class_instance == 0 )
throw bad_instance();
if( _method == 0 )
throw bad_method();
t_return tr;
try {
tr = ( _class_instance->*_method )( parameter );
}
catch(...)
{
throw; // l'appelant se débrouille
}
return tr;
}
// v2 :
on est sur que cette méthode ne déclenchera pas d'autres exceptions.
personellement, je ne définirais pas les classes d'exceptions à l'intérieur
des classes de call_back. Par contre, je les emballerai dans le meme
espace de nommage.
cette solution amene naturellemnt à faire hériter bad_instance, bad_method, bad_call_unexpected et bad_call, de bad_callback (par exemple), lui meme héritant de std::exception (comme c'est le cas).
inline t_return call( t_argument parameter ) throw (bad_instance, bad_method, bad_call, bad_call_unexpected)
{
if( _class_instance == 0 )
throw bad_instance();
if( _method == 0 )
throw bad_method();
t_return tr;
try {
tr = ( _class_instance->*_method )( parameter );
}
catch(const std::exception& e) // eventuellement !
{
throw bad_call(e.what());
}
catch(...)
{
throw bad_call_unexpected();
}
return tr;
}
Je n'ai pas de préférences :/, qu'en penses-tu ?
29 déc. 2004 à 12:50
L'ecriture des classes callback reste perfectible. Mais cela prend une tournure intéressante ! Merci pour tes conseils. ^_^
Cordialement,
X.
28 déc. 2004 à 20:35
pour les exceptions, je songe à une autre conception, faire 2 méthodes dans les t_callback*, une qui n'utilise pas les exceptions (operator()(...)), l'autre qui déclencherai des exceptions, et qui propagerai les exceptions pouvant intervenir dans la fonction appelée. C'est juste une idée ...
"A charge du developpeur soit de completer le throw par une exception standard ou de son cru"
Pourquoi pas une classe d' exception "de son cru" dérivant des exceptions standard ?
"L'appelle d'une fonction (par son pointeur) compte pour 90% dans le temps d'execution du test de callback dynamique."
Je pense qu'un bon optimiseur doit pouvoir éliminer ce code d'erreur, tout est facilement prévisible à la compilation ... Par contre, je ne suis pas sur de la résolution inline de la fonction appelée par l'intermédiaire d'un pointeur de fonction.
Avec ton main, il est intéressant de constater la différence de rapidité d'exécution entre la version const et la version non const (si on compile sans optimisations).
Sinon, ça fait plaisir de voir un programmeur sous w$ évoluant du coté clair :)
@+
28 déc. 2004 à 19:53
28 déc. 2004 à 19:48
Dans l'état, le throw appelle terminate(). C'est un tout petit peu plus propre qu'un segfault (et le docteur watson qui s'en suit). L'idée y est... on peut faire mieux.
28 déc. 2004 à 18:56
Vous etes pardonné mon cher mais que ça ne se renouvelle pas :)
Cette ligne me parait bizarre ...
redéclenchement de quelle exception ?
if( _class_instance 0 && _method 0 ) throw;
il vaudrait mieux déclencher une exception, voire séparer les tests et en déclencher une différente suivant le cas. Ou bien enlever la méthode set et oter les parametres optionels dans le constructeur ? ça restreint un peu son utilisation d'accord ...
28 déc. 2004 à 14:01
Inversement entre un callback dynamique et un callback statique, la perte de temps semble considérable.
A méditer !
27 déc. 2004 à 23:13
27 déc. 2004 à 22:39
t_callback_const( const t_class& c ) : _callback_class( c ) {}
27 déc. 2004 à 22:37
template<
typename t_class,
typename t_return,
typename t_argument,
t_return ( t_class::*fm )( t_argument ) const
>
struct t_callback_const
{
t_callback_const( t_class& c ) : _callback_class( c ) {}
inline t_return operator()( t_argument arg )const
{
return (_callback_class.*fm)( arg );
}
private:
const t_class& _callback_class;
};
pour les exceptions, tu veux pouvoir gérer une méthode genre :
void A::f(void)throw(std::bad_alloc) ? mis à part un catch(...) throw, je ne vois pas comment faire mieux.
"Je suis un peu étonné de ta dernière remarque. Peux-tu préciser ? Ca m'intéresse."
Désolé, rien d'intéressant, juste pour dire que j'ai déjà vu d'horribles programme s(inspiré des pointeurs de fonctions en C) qui utilisaient abusivement les pointeurs de fonctions membres, en détriment d'une conception objet cohérente. De la à la violer ? Je suis en train d'y réfléchir ...
27 déc. 2004 à 18:29
Pour les questions/observations, j'attendais aussi les exceptions... cela dit, je vais prendre en compte cette remarque et proposer le support des fonctions membres conts. A priori, cela oblige à définir deux classes distinctes "callback" très proches l'unes de l'autres. Je vais y réfléchir !
Je suis un peu étonné de ta dernière remarque. Peux-tu préciser ? Ca m'intéresse.
Cordialement,
X.
27 déc. 2004 à 18:15
Tu attends surement qu'on te pose la question : et la "constness" ?
alors, je te la pose :)
Mise à part que les fonctions membres des exemples doivent etre déclarées const, aucune remarque sur le code, j'aime bien.
Mais je considère les procédés de ce genre comme des hacks à n'utiliser que dans des cas bien spécifiques.
27 déc. 2004 à 08:56
A moins de vouloir à tout prix utiliser les MFC dans tes programmes, tu devrais changer de compilateur parce qu'il ne sait pas faire de C++ correctement (en particulier les écritures à base de template).
Je ne peux donc rien faire pour tes erreurs, désolé.
Cordialement,
X.
27 déc. 2004 à 07:38
J'ai compilé avec Visual C++6, et j'ai les erreurs suivantes :
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(17) : error C2973: 't_callback' : invalid template argument 'fm'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(25) : see declaration of 't_callback'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(88) : see reference to class template instantiation 't_callback<struct A,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,
int const &,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall A::fa(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(103) : see reference to class template instantiation 'X<struct A,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
__thiscall A::fa(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(17) : error C2973: 't_callback' : invalid template argument 'fm'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(25) : see declaration of 't_callback'
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(88) : see reference to class template instantiation 't_callback<struct B,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,
int const &,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall B::fb(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(104) : see reference to class template instantiation 'X<struct B,&public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
__thiscall B::fb(int const &)>' being compiled
E:\Program Files\Microsoft Visual Studio\MyProjects\testconsole\testconsole.cpp(107) : warning C4508: 'main' : function should return a value; 'void' return type assumed
Error executing cl.exe.
testconsole.exe - 2 error(s), 1 warning(s)
Faut-il configurer le projet d'une façon spécifique ?