Bonjour,
Je voudrais definir une seul et m�me fonction acceptant le type d'un argument variable comme suit.
Est-ce possible et comment?Code:
1
2
3
4
5
6 std::string toto; double titi; my_func(toto); my_func(titi);
Merci de votre aide
Version imprimable
Bonjour,
Je voudrais definir une seul et m�me fonction acceptant le type d'un argument variable comme suit.
Est-ce possible et comment?Code:
1
2
3
4
5
6 std::string toto; double titi; my_func(toto); my_func(titi);
Merci de votre aide
Bonjour,
Les templates devraient pouvoir r�pondre � ce besoin, non ?
La FAQ d�di�e : http://cpp.developpez.com/faq/cpp/?page=templatesCode:template<typename T> void my_func(T xx);
Cordialement,
A.
Si tu connais les type � l'avance, une simple surcharge peut suffire non ?
Le compilateur passe par une phase dite de "r�solution de surcharge" dans laquelle il compare pour chaque fonction les types qu'on lui donne en argument et les types des diff�rentes surcharges de la fonction qu'il poss�de. Il en d�duit alors automatiquement la bonne surcharge � utiliser.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 void my_func(int i) { //... } void my_func(std::string s) { //.. } std::string s = "toto"; my_func(s);
Salult,
En l'occurrence, pour la std::string l'id�al serait de passer s sous la forme d'une r�f�rence (constante ou non, selon la possibilit� que peut avoir la fonction de modifier la chaine d'origine)
Mais sinon, les deux r�ponses ci-dessus sont effectivement les deux solutions principales:
Soit, tu ne sais pas pr�cis�ment quel type sera transmis � ta fonction, mais tu sais parfaitement ce qu'elle doit faire, quel que soit le type, et, dans ce cas, tu entre de plein pied dans le domaine de la programmation g�n�rique (bienvenue dans le merveilleux monde des template :D:D)
Soit tu connais pr�cis�ment les diff�rents types qui seront pass�s en param�tres, et tu peux appliquer "simplement" le principe de la surcharge de fonctions:
Tout ce qu'il faut, c'est qu'au moins un argument soit de type diff�rent par rapport � l'ensemble des autres signatures possibles, et le type de retour n'intervient pas dans la r�solution de la surcharge ;)
Ok merci pour vos r�ponses.
Au passage je ne sais pas ce qui ce passe mais je n'ai pas �t� averti par emails quelles �taient arriv�es comme d'habitude!
Cela dit, je trouve la solution template bien appropri�e et �l�gante mais j'ai tout de m�me une question.
Comment connaitre dans la focntion le type de donn� envoy� en argument de mani�re � pouvoir int�grer un traitement diff�rent selon que la nature de l'argument.
Parce que si je regarde dans la Faq, je vois bien la m�thode de sp�cialisation, mais ca resemble furieusement � l'autre solution consistant � ecrire une fonction par type. N'y a t-il pas moyen de connaitre le type d'une variable?
Dans ce cas l� c'est peut �tre pr�f�rable d'utiliser une surcharge non?
Comme �a tu peux effectuer les traitements voulus pour chaque type de donn�e s�par�ment.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 void f(int i){ //... } void f(const std::string& s) { //... } f(10); f("toto");
Salut,
Si tu n'as pas besoin de conna�tre le type effectif des param�tres de la fonction, alors oui le template est la solution la plus pertinente.
Si tu as besoin de conna�tre le type effectif des param�tres, alors la surcharge comme propos�e par Arzar est la plus pertinente.
Faire une fonction template en traitant des cas particulier de type est le d�but d'un long chemin d'incompr�hension
Ok, je peux comprendre les sources d'erreurs d'une telle m�thode, je serais tout de m�me interess� de savoir si il existe une moyen de connaitre le type d'une variable.
Ca d�pend de ce que tu entends par l�.
Selon le besoin, il y a les classes traits (mieux �crites et plus compl�tes que l'exemple suivant dans Boost) :
Et il y a typeinfo qui te donne aussi des informations :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 #include <iostream> template<typename T> struct is_bool{static const bool value=false;}; template<> struct is_bool<bool>{static const bool value=true;}; template<class T> void dump() { std::cout<<std::boolalpha<<is_bool<T>::value<<std::endl; } int main() { dump<int>(); dump<bool>(); return 0; }
Sachant que typeid(T) retourne unCode:
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <iostream> #include <typeinfo> template<class T> void dump() { std::cout<<typeid(T).name()<<std::endl; } int main() { dump<int>(); dump<bool>(); return 0; }
name n'est pas d�fini par la norme et est � la discr�tion du compilateur. On se sert plut�t de type_info par comparaison :Code:
1
2
3
4
5
6
7
8
9
10
11 class type_info { public: virtual ~type_info(); bool operator== (const type_info& rhs) const; bool operator!= (const type_info& rhs) const; bool before (const type_info& rhs) const; const char* name() const; private: type_info (const type_info& rhs); type_info& operator= (const type_info& rhs); };
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <iostream> #include <typeinfo> template<class T> void dump() { if(typeid(T)==typeid(bool)){ std::cout<<"c'est un bool"<<std::endl; } if(typeid(T)!=typeid(bool)){ std::cout<<"ce n'est pas un bool"<<std::endl; } } int main() { dump<int>(); dump<bool>(); return 0; }
Ok merci beaucoup, c'est exactement ce que je cherchais
Ceci dit, il y n'y a pas de raison de consid�rer une classe ou une fonction g�n�rique (template) comme "universelle".
Comme les fonctions membres de classes template et les fonctions template d�terminent un comportement particulier, il faut, quoi qu'il en soit, que le type r�ellement manipul� soit "compatible" avec le comportement � mettre en oeuvre.
Ainsi, si tu envisage une fonction, par exemple, add, qui effectue l'addition de deux �l�ments, il faut bien entendu que le type manipul� permette de faire cette addition ;)
L'avantage, c'est que, si tu essaye d'utiliser cette fonction sur un type qui ne supporte pas l'addition, tu aura un message d'erreur d�s la compilation (parce que la r�solution de type s'effectue lors de la compilation), ce qui te permettra au minimum de te poser la question de l'opportunit� d'invoquer cette fonction avec le type en question ;)
L'alternative qui s'offre � toi est alors que
- Soit, il est opportun d'appeler cette fonction, mais il manque alors "quelque chose" (de quoi permettre cette addition, selon l'exemple) dans l'interface publique de ton type particulier
- Soit, il n'est pas opportun de l'appeler, et tu dois revoir ton raisonnement global
Tout � fait d'accord
Quid de boost::variant ?
Exemple et tutoriel ici
C'est bien sur une possibilit� qu'il faut aborder, si cela a un sens...
Mais, de mani�re g�n�rale, je consid�re plus boost::variant comme la possibilit� qu'une m�me variable puisse, � un moment donn�, agir comme un type particulier et � un autre agir comme un type diff�rent...
Ce peut donc �tre une solution, mais il me semble que ce n'est pas le probl�me expos� ici ;):D