Metaprogrammation: Comment détecter si une fonction existe ou pas

Metaprogrammation: Comment détecter si une fonction existe ou pas - C++ - Programmation

Marsh Posté le 07-03-2008 à 17:12:17    

Bonjour,
Dans un code j'aimerai faire le test suivant:
 
     Si la fonction

Code :
  1. template<class T>
  2. stream&<<(stream&,T& )


existe alors je l'utilise, sinon je ne fais rien
 
Normalement pour ca c'est les traits qu'on utilise. Par contre je n'arrive pas à voir comment (et si c'est possible) de tester la présence d'une fonction sans générer de compile time assertion. J'insiste sur ce dernier point!
 
Si vous avez une idée?
 
Merci,

Reply

Marsh Posté le 07-03-2008 à 17:12:17   

Reply

Marsh Posté le 07-03-2008 à 17:45:09    

c'est chelou. Faut trouver un cadre dans lequel tu va pouvoir utilisait la SFINAE. Le problème est que, si al fonction existe pas, bah tu pourra guère tenter de l'utiliser sans erreur de compil.
Ca serait une méthode ça aurait pu etre réglé à coup de boost:has_xxx masi en fonction libre :/

Message cité 1 fois
Message édité par Joel F le 07-03-2008 à 18:19:39
Reply

Marsh Posté le 09-03-2008 à 19:38:18    

Joel F a écrit :

c'est chelou. Faut trouver un cadre dans lequel tu va pouvoir utilisait la SFINAE. Le problème est que, si al fonction existe pas, bah tu pourra guère tenter de l'utiliser sans erreur de compil.
Ca serait une méthode ça aurait pu etre réglé à coup de boost:has_xxx masi en fonction libre :/


 
 
Merci pour ta réponse.
C'est exactement juste la réponse qu'il me fallait, compléter avec un peu de google. En utilisant la SFINAE il est possible de checker l'existence de fonctions membres ou même non membre comme dans mon cas.
Merci Joel pour cette info - j'en ai au passage profiter pour apprendre, comprendre ce que l'on pouvait faire avec cette bete.
 
pour ce qui est de ça:

Citation :

Le problème est que, si al fonction existe pas, bah tu pourra guère tenter de l'utiliser sans erreur de compil.


 
l'utilisation de la SFINAE permet de checker l'existence d'une méthode (membre ou non membre) sans erreur de compile. Ensuite avec le résultat renvoyer par ce mécanisme, rien ne m'empêche d'écrire une class template avec un paramètre bool, et de specialiser avec: true j'utilise la méthode puisqu'elle existe, false et bien je fait rien!
 
Juste pour ceux qui veulent des info pour comprendre comment ca marche, j'ai un lien assez sympa:
http://www.codeproject.com/KB/arch [...] etection12
 
Joel si tu as de la doc un peu plus poussée sur le sujet, je suis preneur!
 
juste pour illustration, un code test que j'ai écrit pour comprendre:
le fichier .h contenant l'ensemble des class et structure nécessaire à la mise en place de ce petit mécanisme:

Code :
  1. #include <ostream>
  2. class toto
  3. {};
  4. class tata
  5. {};
  6. std::basic_ostream<char>& operator<<(std::basic_ostream<char>& stream, const toto& value)
  7. {
  8. return stream;
  9. }
  10. typedef char NotFound; 
  11. struct Found { char x[2]; };
  12. /**
  13. Structure to find functions like std::basic_ostream<char>& std::basic_ostream<char>::operator<<(T)
  14. */
  15. template <class T, std::basic_ostream<char>&  (std::basic_ostream<char>::*)(T) >
  16. struct TestNonStatic_ostream { };
  17. template<class T>
  18. static Found Test_ostream(TestNonStatic_ostream<T,&std::basic_ostream<char>::operator<< >*);
  19. template<class T>
  20. static NotFound Test_ostream( ... );
  21. /**
  22. Structure to find functions like std::basic_ostream<char>& operator<<(std::basic_ostream<char>&, const T& )
  23. */
  24. template <class T, std::basic_ostream<char>& (*)(std::basic_ostream<char>&,const T& ) >
  25. struct TestNonStatic_operator_ref_const { };
  26. template<class T>
  27. static Found Test_operator_ref_const(TestNonStatic_operator_ref_const<T,&operator<< >*);
  28. template<class T>
  29. static NotFound Test_operator_ref_const( ... );
  30. /**
  31. Structure to find functions like std::basic_ostream<char>& operator<<(std::basic_ostream<char>&, T& )
  32. */
  33. template <class T, std::basic_ostream<char>& (*)(std::basic_ostream<char>&, T& ) >
  34. struct TestNonStatic_operator_ref { };
  35. template<class T>
  36. static Found Test_operator_ref(TestNonStatic_operator_ref<T,&operator<< >*);
  37. template<class T>
  38. static NotFound Test_operator_ref( ... );
  39. /**
  40. Structure to find functions like std::basic_ostream<char>& operator<<(std::basic_ostream<char>&, T)
  41. */
  42. template <class T, std::basic_ostream<char>& (*)(std::basic_ostream<char>&, T) >
  43. struct TestNonStatic_operator { };
  44. template<class T>
  45. static Found Test_operator(TestNonStatic_operator<T,&operator<< >*);
  46. template<class T>
  47. static NotFound Test_operator( ... );
  48. template<class T>
  49. struct test
  50. {
  51. static const bool check_presence = (sizeof( Test_ostream<T>    ( 0 ) ) == sizeof(Found)) ||
  52.            (sizeof( Test_operator_ref_const<T> ( 0 ) ) == sizeof(Found)) ||
  53.            (sizeof( Test_operator_ref<T>  ( 0 ) ) == sizeof(Found)) ||
  54.            (sizeof( Test_operator<T>   ( 0 ) ) == sizeof(Found));
  55. };


 
et maintenant le programme principale:

Code :
  1. int main(/*int argc, _TCHAR* argv[]*/)
  2. {
  3. bool test_ = test<int>::check_presence;          // vaut true car la méthode est définit dans la STL
  4. test_ = test<toto>::check_presence;              // vaut true car la méthode est définit dans le .h précédent!
  5. test_ = test<tata>::check_presence;              // vaut false car pas de méthode définit
  6. return 0;
  7. }


 
 
Cdt,

Reply

Marsh Posté le 09-03-2008 à 20:53:35    

papangue a écrit :


l'utilisation de la SFINAE permet de checker l'existence d'une méthode (membre ou non membre) sans erreur de compile. Ensuite avec le résultat renvoyer par ce mécanisme, rien ne m'empêche d'écrire une class template avec un paramètre bool, et de specialiser avec: true j'utilise la méthode puisqu'elle existe, false et bien je fait rien!

 

Ca m'était sorti de la tête, je cherchais à checker qqchose de plus complexe avec un BOOST_TYPEOF, ta solution est bien meilleur.
L'astuce du type de retour de taille différente et de l'utilisation de l'ellipse pour desambiguer est à la base de 51254289 astuces du mêmes genres d'ailleurs.

 
papangue a écrit :


Joel si tu as de la doc un peu plus poussée sur le sujet, je suis preneur!


A part une greffe de cerveau, je n'ai rien à te proposer pour l'instant. N'hésite pas à me contacter ultérieurement si tu cherches d'autre infos.


Message édité par Joel F le 09-03-2008 à 20:57:32
Reply

Marsh Posté le 10-03-2008 à 08:42:04    

par contre le code que j'ai soumis ci-dessus ne fonctionne pas sous VS2005 avec les type templates:
L'opérateur de flux sortant << est codé comme il se doit, mais est template:

Code :
  1. template<class T>
  2. std::ostream& operator<<(std::ostream& stream, const std::vector<T>& value)
  3. {
  4.        // des chose à faire
  5.        return stream;
  6. }


 
mais ce qui est bizarre c'est que
test<std::vector<double> >
me retourne que la fonction n'est pas trouvée.
 
Et là j'ai du mal à saisir la blague... Bref c'est pas totalement gagné pour le moment.
 
Pour contourner le probleme je n'ai pas le choix pour le moment de spécifier des tests supplémentaire pour les vectors avec par exemple:

Code :
  1. template <class T, std::basic_ostream<char>& (*)(std::basic_ostream<char>&,const std::vector<T>& ) >
  2. struct TestNonStatic_operator_ref_const_vect { };
  3. template<class T>
  4. static Found Test_operator_ref_const_vect(TestNonStatic_operator_ref_const_vect<typename T::value_type,&operator<< >*);
  5. template<class T>
  6. static NotFound Test_operator_ref_const_vect( ... );


 
Mais c'est pas très propre.
 
Déjà si quelqu'un peu m'expliquer pourquoi ca ne marche pas, cela me permettrait peut être de corriger mes erreurs.

Reply

Marsh Posté le 10-03-2008 à 19:41:34    

VC++ n'est pas connu pour gérer proprement ce genre d'acrobaties.
Je penche pour une mise en evidence de sa gestion foireuse des spécialisations de templates :/ Rien à faire ...

Reply

Marsh Posté le 10-03-2008 à 21:51:42    

Joel F a écrit :

VC++ n'est pas connu pour gérer proprement ce genre d'acrobaties.
Je penche pour une mise en evidence de sa gestion foireuse des spécialisations de templates :/ Rien à faire ...


 
Merci pour ta réponse. Ceci explique les abbérations de fonctionnement que je retrouve à travers les tests que j'effectuent sous VC++.
 
Bien cordialement,

Reply

Marsh Posté le 10-03-2008 à 21:56:21    

perso, j'ai arrêté Visual et la méta-prog. Y a toujours un cas foireux qui pète au détour d'un cas particulier. Sans compter que VC++ (enfin WC++) ne supporte que partiellement l'ADL et autre truc complètement indispensable.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed