OVH Cloud OVH Cloud

map et operateur []

58 réponses
Avatar
Fanny Chevalier
Bonjour,

Voila, j'ai fait une map :
map <CoupleInt, double>myMap;
destinée a accueillir une valeur relative a un couple d'entiers
CoupleInt dont la syntaxe de classe est la suivante :

class CoupleInt
{
public:
CoupleInt();
CoupleInt(int, int);
CoupleInt(const CoupleInt&);
~CoupleInt();

private:
int first;
int second;
};

Lorsque je fais l'appel (par exemple)
double myDoubleValue = 3.02;
CoupleInt couple = CoupleInt(3,2);
myMap[couple] = myDoubleValue;

il n'a pas l'air d'aimer myMap[couple].

Une idée?

Merci pour votre aide
Fanny

10 réponses

1 2 3 4 5
Avatar
Fabien LE LEZ
On Thu, 07 Oct 2004 15:47:39 +0200, Fanny Chevalier
:

CoupleInt couple = CoupleInt(3,2);


Pas top, ça : tu crées un CoupleInt avec comme arguments 3 et 2, puis
tu le copies.
Mieux vaut écrire tout simplement
CoupleInt couple (3,2);

[Tu ne viendrais pas de Java, par hasard ? ;-)]

myMap[couple] = myDoubleValue;

il n'a pas l'air d'aimer myMap[couple].


Normal. Pour que std::map<> accepte CoupleInt comme clé, il faut un
opérateur < -- ou un foncteur qui fait la même chose, mis en troisième
argument.

Dans ce cas précis, il n'y a pas d'ordre "naturel" sur les CoupleInt,
donc un opérateur < ne me paraît pas justifié -- mieux vaut un
foncteur.

Le problème, c'est que CoupleInt n'offre aucun accès à ses membres
privés, donc il n'est pas possible à une fonction extérieure de
comparer deux CoupleInt.
L'autre problème, c'est que ces membres privés s'appellent "first" et
"second", ce qui risque de porter à confusion, car déréférencer un
itérateur sur un std::map<> donne un std::pair<>, dont les membres
s'appellent aussi first et second. En gros, ça ne posera pas de
problème de compilation, mais sera peu lisible.

Je propose donc le code suivant :

class CoupleInt
{
public:
CoupleInt();
CoupleInt(int, int);

/* Je mets ces deux-là en commentaire car je ne sais pas à quoi ils
servent */
//CoupleInt(const CoupleInt&);
//~CoupleInt();

int GetA() const { return a; }
int GetB() const { return b; }

struct Comparateur
{
bool operator()
(CoupleInt const& lhs, CoupleInt const& rhs) const
{
if (lhs.GetA() < rhs.GetA()) return true;
if (lhs.GetA() > rhs.GetA()) return false;
return lhs.GetB() < rhs.GetB();
}
};

private:
int a;
int b;
};

typedef std::map <CoupleInt, double, CoupleInt::Comparateur>
MonTypeMap;


--
;-)

Avatar
Fanny Chevalier
Fabien LE LEZ wrote:

[Tu ne viendrais pas de Java, par hasard ? ;-)]

Non, mais j'ai toujours du mal avec les constructeurs...


Normal. Pour que std::map<> accepte CoupleInt comme clé, il faut un
opérateur < -- ou un foncteur qui fait la même chose, mis en troisième
argument.

Oui c'est ce que je me suis dis... Il arrive pas a parcourir la map

parce qu'il sait
pas dans quel ordre prendre les elements...

Merci pour ta reponse, ca marche au poil !!!

Avatar
Alexandre
Je propose donc le code suivant :

class CoupleInt
{
public:
CoupleInt();
CoupleInt(int, int);

/* Je mets ces deux-là en commentaire car je ne sais pas à quoi ils
servent */
//CoupleInt(const CoupleInt&);
//~CoupleInt();

int GetA() const { return a; }
int GetB() const { return b; }

struct Comparateur
{
bool operator()
(CoupleInt const& lhs, CoupleInt const& rhs) const
{
if (lhs.GetA() < rhs.GetA()) return true;
if (lhs.GetA() > rhs.GetA()) return false;
return lhs.GetB() < rhs.GetB();
}
};

private:
int a;
int b;
};


pourquoi ne pas faire comme std::pair, une simple structure ?
Ou encore mieux, pourquoi ne pas utiliser std::pair ?
je propose comme code :
typedef std::pair<int,int> CoupleInt;

Avatar
kanze
Fabien LE LEZ wrote in message
news:...

On Thu, 07 Oct 2004 15:47:39 +0200, Fanny Chevalier
:

CoupleInt couple = CoupleInt(3,2);


Pas top, ça : tu crées un CoupleInt avec comme arguments 3 et 2, puis
tu le copies.


Copie que le compilateur est libre à supprimer.

Mieux vaut écrire tout simplement
CoupleInt couple (3,2);


Dans ce cas-ci, il n'y a pas trop de différence. Mais si les
initializateurs était eux-même des constructeurs...

CoupleInt couple( T(i), T(j) ) ;

Ça ne fait pas ce que ça en a l'air.

(Je dis ça simplement pour montrer que le choix n'est pas aussi net que
tu as l'air de dire. En fait, je préfère ta version aussi, d'autant plus
qu'une bonne partie de mes classes ne supportent pas la copie. Mais il y
en a qui préfère la version avec = parce qu'elle évite toute confusion
avec une declaration de fonction.)

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Andre Heinen
On 7 Oct 2004 23:30:02 -0700, wrote:

Fabien LE LEZ wrote in message
news:...

Mieux vaut écrire tout simplement
CoupleInt couple (3,2);


Dans ce cas-ci, il n'y a pas trop de différence. Mais si les
initializateurs était eux-même des constructeurs...

CoupleInt couple( T(i), T(j) ) ;

Ça ne fait pas ce que ça en a l'air.


N'est-ce pas pareil? Quelle est la différence entre
CoupleInt couple( int(3), int(2) );
et
CoupleInt couple(3, 2);
?

(Je dis ça simplement pour montrer que le choix n'est pas aussi net que
tu as l'air de dire. En fait, je préfère ta version aussi, d'autant plus
qu'une bonne partie de mes classes ne supportent pas la copie. Mais il y
en a qui préfère la version avec = parce qu'elle évite toute confusion
avec une declaration de fonction.)


Préfères-tu int i=2; ou int i(2); ?

--
Andre Heinen
My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz


Avatar
Vincent Lascaux
N'est-ce pas pareil? Quelle est la différence entre
CoupleInt couple( int(3), int(2) );
et
CoupleInt couple(3, 2);


Est ce que CoupleInt couple(int(x), int(y)); n'est pas une prédéclaration de
la fonction couple prenant deux arguments entiers ?
Maintenant, pour 3 et 2 ca doit marcher comme prévu...

--
Vincent

Avatar
James Kanze
Andre Heinen writes:

|> On 7 Oct 2004 23:30:02 -0700, wrote:

|> >Fabien LE LEZ wrote in message
|> >news:...

|> >> Mieux vaut écrire tout simplement
|> >> CoupleInt couple (3,2);

|> >Dans ce cas-ci, il n'y a pas trop de différence. Mais si les
|> >initializateurs était eux-même des constructeurs...

|> > CoupleInt couple( T(i), T(j) ) ;

|> >Ça ne fait pas ce que ça en a l'air.

|> N'est-ce pas pareil? Quelle est la différence entre
|> CoupleInt couple( int(3), int(2) );
|> et
|> CoupleInt couple(3, 2);
|> ?

Attention ! Avec des constantes, il n'y a aucune différence. Mais si tu
écris :

CoupleInt couple( int(i), int(j) ) ;

tu as déclaré une fonction (implicitement externe), et non défini une
variable.

Je crois que la plupart des gens considère ça plutôt un boggue qu'un
feature du langage.

|> >(Je dis ça simplement pour montrer que le choix n'est pas aussi net
|> >que tu as l'air de dire. En fait, je préfère ta version aussi,
|> >d'autant plus qu'une bonne partie de mes classes ne supportent pas
|> >la copie. Mais il y en a qui préfère la version avec = parce
|> >qu'elle évite toute confusion avec une declaration de fonction.)

|> Préfères-tu int i=2; ou int i(2); ?

En ce qui concerne les types de bases, de pointeurs et des références,
j'utilise plutôt « int i = 2 ». Plus par habitude que par préférence.

Pour toute la reste, j'utilise prèsqu'exclusivement la forme avec
parenthèses. Éventuellement avec des parenthèses supplémentaires pour
désambuiguer :

CoupleInt couple( (T(i)), (T(j)) ) ;

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
Benoît Dejean
Le Sat, 09 Oct 2004 12:38:23 +0200, James Kanze a écrit :


désambuiguer :


joli. <clap clap>

j'arrive même pas à le prononcer :)

Avatar
James Kanze
Benoît Dejean writes:

|> Le Sat, 09 Oct 2004 12:38:23 +0200, James Kanze a écrit :

|> > désambuiguer :

|> joli. <clap clap>

|> j'arrive même pas à le prononcer :)

Peut-être si je l'avais écrit : « désambigüer » ? Encore que pour la
prononciation...:-). (C'est à peu près ce que j'ai voulu écrire, en tout
cas.)

Ce n'est même pas un anglicisme. « Disambiguate » ne résonne pas mieux
en anglais. Mais j'aimerais bien avoir un mot pour la chose (encore
qu'au fond, lever l'ambiguïté me semble faire l'affaire d'une façon
suffisante). Je ne pourrais même pas blâmer mes sejours en Allemagne.
Les allemands aiment bien créer de nouveaux mots, mais ça ne me
viendrait pas à l'esprit non plus d'y écrire « entdoppeldeutigen ».
(Encore qu'au moins, un allemand saurait le prononcer, et comprendra ce
qu'il signifie.)

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
Fabien LE LEZ
On Thu, 7 Oct 2004 22:58:36 +0200, "Alexandre"
:

pourquoi ne pas faire comme std::pair, une simple structure ?


Petit détail de vocabulaire : le mot "struct" déclare/définit une
classe. Il n'y a pas de structures en C++.

Mais j'imagine que tu voulais parler d'une classe où tous les membres
sont publics.
C'est peut-être très bien pour un exemple simple, mais j'imagine que
l'OP voulait étendre le bazar pour faire un truc un peu plus complexe.

Ou encore mieux, pourquoi ne pas utiliser std::pair ?


Ben... franchement, je n'ai encore jamais eu l'occasion d'utiliser
std::pair<>. Je me demande même si cette classe n'a pas été créée
uniquement comme helper pour std::map<>.


--
;-)

1 2 3 4 5