PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > fr.comp.lang.c++ > Composition de function avec un "Non-Type Template Parameters"
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Composition de function avec un "Non-Type Template Parameters"

Réponse
 
LinkBack Outils de la discussion
Vieux 29/04/2008, 21h58   #1
plouf
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Composition de function avec un "Non-Type Template Parameters"

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
  Réponse avec citation
Vieux 30/04/2008, 08h54   #2
Ael Rowen Terence
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"


"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 !


  Réponse avec citation
Vieux 30/04/2008, 13h49   #3
Michael DOUBEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

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
  Réponse avec citation
Vieux 30/04/2008, 21h15   #4
plouf
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

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
  Réponse avec citation
Vieux 01/05/2008, 03h31   #5
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

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);
}



  Réponse avec citation
Vieux 01/05/2008, 03h39   #6
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

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));
}

  Réponse avec citation
Vieux 01/05/2008, 03h53   #7
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

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));
}

  Réponse avec citation
Vieux 01/05/2008, 04h20   #8
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

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>();
}

  Réponse avec citation
Vieux 01/05/2008, 21h46   #9
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

> fonction f= Composeur(square,twice).GetF<square,twice>();

Et évidemment, on peut utiliser une macro pour éviter la répétition :

#define COMPOSE( f1, f2) (Composeur(f1,f2).GetF<f1,f2>())

fonction f= COMPOSE (square, twice);

  Réponse avec citation
Vieux 02/05/2008, 23h02   #10
plouf
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

Fabien LE LEZ a écrit :
>> fonction f= Composeur(square,twice).GetF<square,twice>();

>
> Et évidemment, on peut utiliser une macro pour éviter la répétition :
>
> #define COMPOSE( f1, f2) (Composeur(f1,f2).GetF<f1,f2>())
>
> fonction f= COMPOSE (square, twice);
>


J'aime bien tes deux méthodes. De mon coté je suis parti un peu sur une autre
voix en remplaçant les trois "int" par le type des deux méthodes et en essayant
de faire quelque chose qui permette de composer des fonction composée. Je suis
arrivé à un truc assez marrant qui permet de "définir" les nouvelles fonction
avec des typedef. La syntaxe et horrible et je ne pense pas que j'utiliserais ça
un jour dans un vrai programme :-D


#include <iostream>
#include <string>
#include <sstream>

using std::string;

template<typename F> class fct_type;

template<typename Res, typename Arg>
struct fct_type<Res (*)(Arg)>
{
typedef Res res;
typedef Arg arg;
};


template<typename F, typename G>
struct compose
{
typedef typename fct_type<F>::res F_res;
typedef typename fct_type<F>::arg F_arg;
typedef typename fct_type<G>::res G_res;
typedef typename fct_type<G>::arg G_arg;

template<F_res f(F_arg), G_res g(G_arg)>
struct prm
{
typedef F_res (*type)(G_arg);

static F_res func(G_arg arg)
{
return f(g(arg));
}
};
};

int twice(int a)
{
return 2*a;
}

int square(int a)
{
return a*a;
}

std::string toString (int i)
{
std::stringstream sstr;
sstr << "STR(" << i << ")";
return sstr.str();
}

void test(int n)
{
typedef int (* i_i)(int); // int -> int
typedef string (* i_s)(int); // int -> string

typedef compose<i_i,i_i>::prm<square,twice> sqr_tw;
typedef compose<i_i,i_i>::prm<twice,twice> x4;
typedef compose<i_i,i_i>::prm<square,square> sqr_sqr;
typedef compose<i_i,i_i>::prm<square,sqr_tw::func> sqr_sqr_tw1;
typedef compose<i_i,i_i>::prm<sqr_sqr::func,twice> sqr_sqr_tw2;
// On peut utiliser i_i ou "x4::type" si on ne connait pas le type
typedef compose<i_i,x4::type>::prm<x4::func,x4::func> x16;
typedef compose<i_s,x16::type>::prm<toString,x16::func> x16_str;

std::cout << sqr_tw::func(n) << " :: " << square(twice(n)) << std::endl;
std::cout << sqr_sqr_tw1::func(n) << " :: " << square(square(twice(n))) <<
std::endl;
std::cout << sqr_sqr_tw2::func(n) << " :: " << square(square(twice(n))) <<
std::endl;
std::cout << x16_str::func(n) << " :: " << x4::func(x4::func(n)) << std::endl;
std::cout << std::endl;
}

int main()
{
test(4);
test(5);
test(6);

return 0;
}


Seb
  Réponse avec citation
Vieux 05/05/2008, 03h56   #11
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

On Sat, 03 May 2008 00:02:26 +0200, plouf <plouf79@yahoo.fr>:

>La syntaxe et horrible


Comme tu dis. Mais le préprocesseur doit pouvoir aider, non ?


  Réponse avec citation
Vieux 05/05/2008, 08h37   #12
Michael DOUBEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

Fabien LE LEZ a écrit :
> 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.


Oui. Ce n'est pas ce que j'ai dit. J'ai dit que la spécialisation du
template se faisait par valeur (valeur d'un pointeur sur fonction) et
que nous ne pouvions pas avoir une valeur sans typage.

J'ai eu tort de mentionner la surcharge de fonction, l'exemple n'est pas
approprié. Tu as raison sur ce point.

Michael
  Réponse avec citation
Vieux 05/05/2008, 13h41   #13
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Composition de function avec un "Non-Type Template Parameters"

On Mon, 05 May 2008 09:37:32 +0200, Michael DOUBEZ
<michael.doubez@free.fr>:

>Oui. Ce n'est pas ce que j'ai dit. J'ai dit que la spécialisation du
>template se faisait par valeur (valeur d'un pointeur sur fonction) et
>que nous ne pouvions pas avoir une valeur sans typage.


Certes, mais ça ne veut pas dire que le programmeur doit expliciter le
type.

>J'ai eu tort de mentionner la surcharge de fonction, l'exemple n'est pas
>approprié.


Sauf qu'en l'occurence, c'est effectivement le cas qui pose problème.

  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 07h11.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières ©2000-2008
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,19037 seconds with 21 queries