Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

conteneurs et methodes templates, et autres petites questions

1 réponse
Avatar
Jeremie Fouche
Bonjour, bonjour

But du code (le code est a la fin du post) :
Ranger des tempos dans une trame musicale, et donner le tempo à n'importe
quelle position dans la trame.
La map contient les changements de tempo. Le code n'est pas complet,
notement en ce qui concerne CTrame::SetTempo, mais le propos n'est pas là.
Dans un avenir <tres> proche, je souhaite aussi rajouter des changements
de signature, de partie,... C'est le but de la classe template mapPos.

Le code fonctionne, et le résulat correspond à mes attente, mais... (sinon,
c'est pas drole :)

Questions :
Pourquoi les warnings dus à un typename implicite lors de la création de
l'iterateur dans la fonction template CTrame::GetChange() ?
Par la meme occasion, que signifie typename, car j'ai pas bien compris la
doc :(
Le conteneur map est il bien adapté à ce genre de conception ?
La classe template mapPos est vide, et ca me choque un peu, mais rassurez
moi, ca ne pose aucun problème ?
Les méthodes template CTrame::GetChange() et CTrame::SetChange() ne
doivent elle pas etre plutot des fonctions externes à la classe CTrame ?
Pourquoi le compilateur n'accepte pas que je supprime le commentaire dans
la méthode CTrame::Out(). Si je me suis competement planté, y a t il un
moyen d'utiliser directement la fonction copy(begin, end, ostream_iterator)
dans la méthode template CTrame::Out(mapPos), ou bien faut il que je créé
une fonction template operator<<(ostream os, pair<int,T>) (non testé), ou
bien encore que je dérive un classe de ostream_iterator<pair<int,T>> et une
fonction operator<<(ostream, pair<int,T>) (nom testé nom plus), ou bien je
divague dans les spheres éthérés ?
Bon, je crois que ca suffit pour le moment. Merci pour ceux qui prendront
le soin de me repondre... Aïe, Pas sur la tête, je débute.

#include <iostream>
#include <map>

using namespace std;

bool inRange(int val, int min, int max)
{
return ( (val>=min) && (val<=max) );
}

//////////////////////////////////////////////
class CTempo
{
friend ostream& operator<<(ostream &os, const CTempo& tempo);

public:
CTempo():m_value(0) {}
CTempo(int value):m_value(value) {}
virtual ~CTempo(){}

protected:
enum { TEMPO_MIN=20, TEMPO_MAX=255 };

int m_value;

public:
//////////////////////////
int GetValue(void) const
{
return m_value;
}

//////////////////////////
bool SetValue(int value)
{
bool bRetour = false;
if ( inRange(value, TEMPO_MIN, TEMPO_MAX) )
{
m_value = value;
bRetour = true;
}
return bRetour;
}
};

//////////////////////////
ostream& operator<<(ostream &os, const CTempo& tempo)
{
os << tempo.m_value << " BPM";
return os;
}

//////////////////////////
template <class T>
class mapPos : public map<unsigned int,T>
{
};

typedef mapPos<CTempo> mapTempo;
typedef mapTempo::iterator iterTempo;
typedef mapTempo::const_iterator c_iterTempo;

//////////////////////////////////////////////
class CTrame
{
public:
CTrame(){}
virtual ~CTrame(){}

protected:
mapTempo m_mapTempo;

public:
//////////////////////////
CTempo GetTempo(unsigned int pos) const
{
return GetChange(m_mapTempo, pos);
}

//////////////////////////
void SetTempo(unsigned int pos, const CTempo& tempo)
{
SetChange(pos, m_mapTempo, tempo);
}

//////////////////////////
void Out() const
{
for (c_iterTempo iTempo=m_mapTempo.begin(); iTempo!=m_mapTempo.end();
++iTempo)
{
cout << (*iTempo).first << ":" << (*iTempo).second << endl;
}
// Out(m_mapTempo);
}
protected:
//////////////////////////
template<class T>
T GetChange(const mapPos<T>& rMapPos, unsigned int pos) const
{
mapPos<T>::const_iterator idx = rMapPos.find(pos);
if (idx == rMapPos.end())
{
idx = rMapPos.lower_bound(pos);
--idx;
}
return (*idx).second;
}

//////////////////////////
template<class T>
void SetChange(unsigned int pos, mapPos<T>& rMapPos, const T& t)
{
if ( rMapPos.insert(mapPos<T>::value_type(pos, t) ).second == false)
{
(*(rMapPos.find(pos))).second = t;
}
}

//////////////////////////
template<class T>
void Out(const mapPos<T>& rMapPos) const
{
mapPos<T>::value_type pairPosT;
copy( rMapPos.begin(), rMapPos.end()
, ostream_iterator<pairPosT>(cout, "\n"));
// A FAIRE : besoin tres probable de operator<<(os,
mapPos<T>::value_type)
}
};

//////////////////////////////////////////////
int main(void)
{
CTrame trame;
trame.SetTempo( 0, CTempo(120));
trame.SetTempo( 10, CTempo(140));
trame.SetTempo( 10, CTempo(150));

cout << "Recherche du tempo(0) : " << trame.GetTempo(0) << endl;
cout << "Recherche de tempo(5) : " << trame.GetTempo(5) << endl;
cout << "Recherche de tempo(10) : " << trame.GetTempo(10) << endl;
cout << "Recherche de tempo(15) : " << trame.GetTempo(15) << endl;

return 0;
}

1 réponse

Avatar
Franck Branjonneau
"Jeremie Fouche" écrivait:

But du code (le code est a la fin du post) :
Ranger des tempos dans une trame musicale, et donner le tempo à n'importe
quelle position dans la trame.


J'ignore ce que sont des tempos et des trames musicales.

La map contient les changements de tempo. Le code n'est pas complet,
notement en ce qui concerne CTrame::SetTempo, mais le propos n'est pas là.
Dans un avenir <tres> proche, je souhaite aussi rajouter des changements
de signature, de partie,... C'est le but de la classe template mapPos.


Signature ? Partie ?

Le code fonctionne, et le résulat correspond à mes attente,


C'est déjà bien.

Questions :
Pourquoi les warnings dus à un typename implicite lors de la création de
l'iterateur dans la fonction template CTrame::GetChange() ?


Pour te mettre en garde.

Par la meme occasion, que signifie typename, car j'ai pas bien compris la
doc :(


Deux utilisitations : dans une liste d'arguments templates où il peut
être remplacé par class (la réciproque est fausse) ; dans le code
template pour affirmer que tu as un type.

Le conteneur map est il bien adapté à ce genre de conception ?


J'ignore tout du domaine (le solfège ?). Est-ce qu'une trame ne
pourrait pas être un tableau de paires (date, tempo) ?

La classe template mapPos est vide, et ca me choque un peu, mais rassurez
moi, ca ne pose aucun problème ?


Qu'une classe soit vide ne pose pas de problèmes. L'héritage d'une
classe template par une autre classe template est plus problèmatique :

// test.cc
template< typename _X >
struct Foo { int boom() { return 0; } };

int boom() { return 1; }

template< typename _X >
struct Bar: Foo< _X > { int youpla() { return boom(); } };

int main() { return Bar< void >().youpla(); }


c++ test.cc; ./a.out && echo OK
OK



~/bin/c++ test.cc; ./a.out && echo OK



Le bon résultat est le second.

Les méthodes template CTrame::GetChange() et CTrame::SetChange() ne
doivent elle pas etre plutot des fonctions externes à la classe
CTrame ?


Certainement puisqu'elles n'accèdent à aucun membre de CTrame.
Et comme elles travaillent sur une maPos, elles pourraient devenir
membre de maPos.

template <class T>
class mapPos {

map<unsigned int,T> theMap_;

public:
T GetChange(unsigned int pos) const;
void SetChange(unsigned int pos, const T& t);

};

Pourquoi le compilateur n'accepte pas que je supprime le commentaire dans
la méthode CTrame::Out().


Lis le message d'erreur.

Si je me suis competement planté, y a t il un moyen d'utiliser
directement la fonction copy(begin, end, ostream_iterator) dans la
méthode template CTrame::Out(mapPos), ou bien faut il que je créé
une fonction template operator<<(ostream os, pair<int,T>) (non
testé), ou bien encore que je dérive un classe de
ostream_iterator<pair<int,T>> et une fonction operator<<(ostream,
pair<int,T>) (nom testé nom plus), ou bien je divague dans les
spheres éthérés ?


Au choix. Que reproches-tu à ta fonction ?
Note que, comme précédemment, CTrame::Out(mapPos const &) const
pourrait devenir mapPos::Out() const.

Bon, je crois que ca suffit pour le moment. Merci pour ceux qui
prendront le soin de me repondre...


Si tu posais une question par post, ce serait plus facile.
--
Franck Branjonneau