|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 (permalink) |
|
Messages: n/a
Hébergeur: |
Bonjour à tous,
J'ai essayé de faire un template qui donne la fonction composée de deux fonction (sans utilisé de "functor"). Je suis arrivé à ça : #include <iostream> template<typename T1,typename T2,typename T3, T1 f1(T2), T2 f2(T3)> T1 compose_fct(T3 arg) { return f1(f2(arg)); }; int twice(int a) { return 2*a; } int square(int a) { return a*a; } int main() { int (*sqr_tw)(int) = compose_fct<int,int,int,square,twice>; std::cout << sqr_tw(4) << " :: " << square(twice(4)) << std::endl; std::cout << sqr_tw(5) << " :: " << square(twice(5)) << std::endl; std::cout << sqr_tw(6) << " :: " << square(twice(6)) << std::endl; return 0; } (testé avec gcc 3.4.4 et VS2005) Je trouve dommage d'être obligé de mettre ces 3 "int" dans compose_fct<int,int,int,square,twice> alors qu'on a toutes les informations nécéssaire avec le type des functions. Personne n'a une idée pour améliorer ça ? Seb |
|
|
|
#2 (permalink) |
|
Messages: n/a
Hébergeur: |
"plouf" <plouf79@yahoo.fr> a écrit dans le message de news: LZLRj.106$yk.36@nntpserver.swip.net... > Bonjour à tous, > > J'ai essayé de faire un template qui donne la fonction composée de deux > fonction (sans utilisé de "functor"). Je suis arrivé à ça : > > #include <iostream> > > template<typename T1,typename T2,typename T3, T1 f1(T2), T2 f2(T3)> > T1 compose_fct(T3 arg) > { > return f1(f2(arg)); > }; > > int twice(int a) > { > return 2*a; > } > > int square(int a) > { > return a*a; > } > > int main() > { > int (*sqr_tw)(int) = compose_fct<int,int,int,square,twice>; > > std::cout << sqr_tw(4) << " :: " << square(twice(4)) << std::endl; > std::cout << sqr_tw(5) << " :: " << square(twice(5)) << std::endl; > std::cout << sqr_tw(6) << " :: " << square(twice(6)) << std::endl; > > return 0; > } > > (testé avec gcc 3.4.4 et VS2005) > > Je trouve dommage d'être obligé de mettre ces 3 "int" dans > compose_fct<int,int,int,square,twice> alors qu'on a toutes les > informations nécéssaire avec le type des functions. > > Personne n'a une idée pour améliorer ça ? Très intéressant. Bravo ! |
|
|
|
#3 (permalink) |
|
Messages: n/a
Hébergeur: |
plouf a écrit :
> Bonjour à tous, > > J'ai essayé de faire un template qui donne la fonction composée de > deux fonction (sans utilisé de "functor"). Je suis arrivé à ça : [snip] > int (*sqr_tw)(int) = compose_fct<int,int,int,square,twice>; [snip] > Je trouve dommage d'être obligé de mettre ces 3 "int" dans > compose_fct<int,int,int,square,twice> alors qu'on a toutes les > informations nécéssaire avec le type des functions. > > Personne n'a une idée pour améliorer ça ? Pas vraiment. Spécialiser sur R(*T)(P) est spécialiser sur une valeur; pour avoir une valeur, on est bien obligé d'avoir un type. Imagine que square ait plusieurs spécialisations: double square(double) float square(float) int square(int) Se contenter de: compose_fct<square,twice> ne permettrait pas de choisir la bonne valeur. -- Michael |
|
|
|
#4 (permalink) |
|
Messages: n/a
Hébergeur: |
Michael DOUBEZ a écrit :
.... > > Pas vraiment. Spécialiser sur R(*T)(P) est spécialiser sur une valeur; > pour avoir une valeur, on est bien obligé d'avoir un type. > > Imagine que square ait plusieurs spécialisations: > double square(double) > float square(float) > int square(int) > > Se contenter de: > compose_fct<square,twice> > ne permettrait pas de choisir la bonne valeur. > Ah oui, je n'avais pas pensé à ça. C'est donc logique qu'on ne puisse pas simplifier plus. Merci. Seb |
|
|
|
#5 (permalink) |
|
Messages: n/a
Hébergeur: |
30 Apr 2008 14:49:46 +0200, Michael DOUBEZ :
>Imagine que square ait plusieurs spécialisations: >double square(double) >float square(float) >int square(int) Mais en l'occurence, on n'en a qu'une. Le compilateur est capable de déduire les types qui vont bien dans un tel cas. Exemple : le code ci-dessous est parfaitement valide, et cesse de l'être quand on enlève les "//". int square (int); //double square (double); template <class Resultat, class Argument> void F (Resultat (*fct) (Argument)) {} int main() { F (square); } |
|
|
|
#6 (permalink) |
|
Messages: n/a
Hébergeur: |
On Tue, 29 Apr 2008 22:58:53 +0200, plouf <plouf79@yahoo.fr>:
>[...] J'ai bien conscience que le code ci-dessous ne répond pas à la question, mais c'est la seule solution que j'aie trouvé pour ne jamais avoir à écrire les types dans le code client. template <typename Resultat, typename Intermediaire, typename Argument> class FoncteurCompose_t { public: typedef Resultat (*Fonction1)(Intermediaire); typedef Intermediaire (*Fonction2)(Argument); FoncteurCompose_t (Fonction1 f1_, Fonction2 f2_) : f1 (f1_), f2 (f2_) {} Resultat operator () (Argument const& a) const { return f1(f2(a)); } private: Fonction1 f1; Fonction2 f2; }; template <typename Resultat, typename Intermediaire, typename Argument> FoncteurCompose_t <Resultat, Intermediaire, Argument> FoncteurCompose (Resultat (*f1)(Intermediaire), Intermediaire (*f2)(Argument)) { return FoncteurCompose_t <Resultat, Intermediaire, Argument> (f1, f2); } int twice(int a) { return 2*a; } int square(int a) { return a*a; } #include <iostream> template <class F> void Teste (F f) { std::cout << f(4) << " :: " << square(twice(4)) << std::endl; std::cout << f(5) << " :: " << square(twice(5)) << std::endl; std::cout << f(6) << " :: " << square(twice(6)) << std::endl; } int main() { Teste (FoncteurCompose (square, twice)); } |
|
|
|
#7 (permalink) |
|
Messages: n/a
Hébergeur: |
On Tue, 29 Apr 2008 22:58:53 +0200, plouf <plouf79@yahoo.fr>:
>[...] J'ai bien conscience que le code ci-dessous ne répond pas à la question, mais c'est la seule solution que j'aie trouvé pour ne jamais avoir à écrire les types dans le code client. template <typename Resultat, typename Intermediaire, typename Argument> class FoncteurCompose_t { public: typedef Resultat (*Fonction1)(Intermediaire); typedef Intermediaire (*Fonction2)(Argument); FoncteurCompose_t (Fonction1 f1_, Fonction2 f2_) : f1 (f1_), f2 (f2_) {} Resultat operator () (Argument const& a) const { return f1(f2(a)); } private: Fonction1 f1; Fonction2 f2; }; template <typename Resultat, typename Intermediaire, typename Argument> FoncteurCompose_t <Resultat, Intermediaire, Argument> FoncteurCompose (Resultat (*f1)(Intermediaire), Intermediaire (*f2)(Argument)) { return FoncteurCompose_t <Resultat, Intermediaire, Argument> (f1, f2); } int twice(int a) { return 2*a; } int square(int a) { return a*a; } #include <iostream> template <class F> void Teste (F f) { std::cout << f(4) << " :: " << square(twice(4)) << std::endl; std::cout << f(5) << " :: " << square(twice(5)) << std::endl; std::cout << f(6) << " :: " << square(twice(6)) << std::endl; } int main() { Teste (FoncteurCompose (square, twice)); } |
|
|
|
#8 (permalink) |
|
Messages: n/a
Hébergeur: |
On Tue, 29 Apr 2008 22:58:53 +0200, plouf <plouf79@yahoo.fr>:
> Je trouve dommage d'être obligé de mettre ces 3 "int" dans >compose_fct<int,int,int,square,twice> alors qu'on a toutes les informations >nécéssaire avec le type des functions. J'ai trouvé le moyen d'éviter de spécifier ces trois "int"... à condition de taper les noms des fonctions deux fois ! C'est le code le plus tordu que j'aie pondu depuis un bout de temps... /* La fonction finale. Aux noms des identifiants près, il s'agit de ton code. */ template <typename Resultat, typename Intermediaire, typename Argument, Resultat f1 (Intermediaire), Intermediaire f2 (Argument)> Resultat compose_fct(Argument arg) { return f1(f2(arg)); }; /* Ici, on sépare les arguments templates "types" des arguments templates "fonctions". L'idée : puisque les deux fonctions sont des arguments templates, il faut que les trois types soient déjà définis. La seule façon de faire, c'est de mettre "GetF" dans une classe template. */ template <typename Resultat, typename Intermediaire, typename Argument> struct Composeur_t { typedef Resultat (*Reponse) (Argument); template <Resultat f1 (Intermediaire), Intermediaire f2 (Argument)> Reponse GetF() const { return compose_fct <Resultat, Intermediaire, Argument, f1, f2>; } }; /* Le compilateur est capable de déduire automatiquement les paramètres template pour une fonction, mais pas pour une classe. On crée donc une fonction "er" qui crée un objet de type Composeur_t. */ template <typename Resultat, typename Intermediaire, typename Argument> Composeur_t <Resultat, Intermediaire, Argument> Composeur (Resultat (*f1)(Intermediaire), Intermediaire (*f2)(Argument)) { return Composeur_t <Resultat, Intermediaire, Argument>(); } // Tes deux fonctions int twice(int a) { return 2*a; } int square(int a) { return a*a; } // Le code utilisateur int main() { typedef int (*fonction) (int); fonction f= Composeur(square,twice).GetF<square,twice>(); } |
|
![]() |
| Outils de la discussion | |
|
|