
Envoyé par
thibouille
Maintenant j'ai eu un petit soucis que j'ai réglé mais
"à la bourrin". J'ai une fonction chargée de calculer effectif x valeur.
1 2 3 4 5 6 7 8 9
| short geteffxval(list<ELEM_C> & _liste_d, double &_sommeeffxval){
list<ELEM_C>::iterator i = _liste_d.begin();
while (i!= _liste_d.end())
{
i->puteffxval(i->geteff()*i->getcentre());
_sommeeffxval=_sommeeffxval+i->geteff()*i->getcentre();
i++;
}
return 0;}; |
Quelques petites remarques sur le style:
- les identificateurs commençant par un underscore et ceux qui en comportent deux de suite sont réservés pour l'implémentation (les règles sont un peu plus complexes que ça, mais retenir celle-ci est facile et ne génère aucun problème). Il vaut mieux les éviter parce que d'une implémentation à l'autre, ceux qui sont réellement utilisés varient;
- il est courant de réserver les identificateurs tout en capitale pour le préprocesseur;
- j'aime pas trop le mélange de l'anglais et du français, et encore moins une syntaxe anglais avec des mots français (effectif x valeur);
- tu ne modifies pas la liste, pourquoi ce paramètre n'est-il pas const?
- je n'aime pas du tout les méthodes de nommage qui n'offrent aucune indication sur la séparation des mots dans les noms.
Je pourrais surdéfinir (je l'ai fait ça tourne très bien) et ajouter:
1 2 3 4 5 6 7 8 9
| short geteffxval(list<ELEM_D> & _liste_d, double &_sommeeffxval){
list<ELEM_D>::iterator i = _liste_d.begin();
while (i!= _liste_d.end())
{
i->puteffxval(i->geteff()*i->getval());
_sommeeffxval=_sommeeffxval+i->geteff()*i->getval();
i++;
}
return 0;}; |
Les différences sont que la première prend une list<ELEM_C> et appelle getcentre() alors que la seconde prend une liste <ELEM_D> et appelle getval().
Mais pourquoi pas une template?
Comme paramètre template, tu peux avoir des pointeurs sur fonction membre.
1 2 3 4 5 6 7 8 9 10 11
| template <typename Ty, double(Ty::* func)()>
short geteffxval(list<Ty>& _liste_d, double &_sommeeffxval){
list<Ty>::iterator i = _liste_d.begin();
while (i != _liste_d.end())
{
i->puteffxval(i->geteff() * ((*)i.*func)());
_sommeeffxval = _sommeeffxval + i->geteff() * ((*i).*func)();
i++;
}
return 0;
}; |
à appeler:
geteffxval<ELEM_D, &ELEM_D::getval>(liste, somme);
C'est pas très pratique à appeler. Donc on peut utiliser la technique des traits pour donner une valeur par défaut convenable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| template <typename Ty>struct EffXValTrait{};
template <> struct EffXValTrait<ELEM_D> {
static double (ELEM_D::*func)();
}
double (ELEM_D::* EffXValTrait<ELEM_D>::func)()
= &ELEM_D::getval;
template <> struct EffXValTrait<ELEM_C> {
static double (ELEM_C::*func)() = &ELEM_C::getcentre;
}
double (ELEM_C::* EffXValTrait<ELEM_C>::func)()
= &ELEM_C::getval;
template <typename Ty>
short geteffxval(list<Ty>& _liste_d, double &_sommeeffxval){
list<Ty>::iterator i = _liste_d.begin();
while (i != _liste_d.end())
{
i->puteffxval(i->geteff() * ((*)i.*(EffXValTraits<Ty>::func))());
_sommeeffxval = _sommeeffxval + i->geteff()
* ((*i).*(EffXValTraits<Ty>::func))();
i++;
}
return 0;
}; |
qu'on appelle par Généralement, on utilise un paramètre template avec une valeur par défaut pour les traits, mais de tels paramètres ne sont pas autorisés pour les fonctions. Un exemple qui compile si le copier/coller ne m'a pas joué un tour que je n'ai pas vu (il m'en a joué que j'ai remarqués):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include <iostream>
#include <list>
#include <assert.h>
class Continuous
{
public:
double getCenter() const { return 0; }
};
class Discrete
{
public:
double getValue() const { return 0; }
};
template <typename Ty, double (Ty::*func)() const>
double mean(std::list<Ty> const& l)
{
double sum;
assert(l.size() != 0);
typedef typename std::list<Ty>::const_iterator Iter;
for (Iter i = l.begin(),
e = l.end();
i != e;
++i)
{
sum += ((*i).*func)();
}
return sum/l.size();
}
template <typename Ty> struct MeanTraits {};
template <> struct MeanTraits<Continuous>
{
static double (Continuous::*func)() const;
};
double (Continuous::* MeanTraits<Continuous>::func)() const
= &Continuous::getCenter;
template <> struct MeanTraits<Discrete>
{
static double (Discrete::*func)() const;
};
double (Discrete::* MeanTraits<Discrete>::func)() const
= &Discrete::getValue;
template <typename Ty>
double meanWithTraits(std::list<Ty> const& l)
{
double sum;
assert(l.size() != 0);
typedef typename std::list<Ty>::const_iterator Iter;
for (Iter i = l.begin(),
e = l.end();
i != e;
++i)
{
sum += ((*i).*(MeanTraits<Ty>::func))();
}
return sum/l.size();
}
int main()
{
std::list<Continuous> lc;
std::list<Discrete> ld;
std::cout << mean<Continuous, &Continuous::getCenter>(lc)
<< mean<Discrete, &Discrete::getValue>(ld)
<< meanWithTraits(lc)
<< meanWithTraits(ld);
} |
Partager