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

size_t vs vector::size_type

24 réponses
Avatar
Michel Michaud
Il me semble que James a déjà démontré par des articles de la norme,
que vector<>::size_type ne peut pas être différent de size_t. Je me
trompe ?

Est-il alors « correct » d'écrire :

vector<TypeQuelconque> v;
...
for (size_t i= 0; i != v.size(); ++i)
...

Je trouve difficile d'introduire vector::size_type rapidement.
Surtout lorsque les vecteurs contiennent des types personnels :

for (vector<TypeQuelconque>::size_type i= 0; i != v.size(); ++i)

C'est terriblement lourd, il me semble. Au point où il apparaît
qu'un typedef (pour vector<TypeQuelconque>::size_type) serait très
utile. Mais est-ce raisonnable de faire un typedef pour chaque type
de vector (dans bien des programmes, il en faudrait un pour
vector<int>::size_type, un autre pour vector<double>::size_type,
etc.) si size_t fera l'affaire dans tous les cas ?

J'utilise actuellement int dans les premiers exemples que je donne
à mes élèves, mais le compilateur peut donner des avertissements,
justifiés, car il y a alors mélange signé/non signé dans les
comparaisons avec size() et il est facile d'imaginer que int n'est
pas suffisant pour toutes les tailles possibles des vecteurs (en
particulier, si int a 16 bits). J'aimerais donc faire mieux, mais
sans avoir à expliquer les types imbriqués, les typedef, etc.,
avant d'avoir expliqué l'utilisation simple des vecteurs ! Dois-
je revenir aux vecteurs de base à la C ? J'aimerais mieux pouvoir
simplement utiliser size_t !

L'emploi de valeurs non signées comme indice n'est pas sans
problème non plus, car il est assez fréquent qu'un indice serve
dans un calcul mettant en scène des valeurs signées. Là encore,
le compilateur peut donner des avertissements... Inversement on
peut vouloir calculer un indice à partir de valeurs signées,
mais qui aimera écrire

int indice= ...
...
v[static_cast<vector<TypeQuelconque>::size_type>(indice)]

au lieu de v[indice] !

N.B. BS utilise normalement int dans TC++PL... Je crois que je
vais lui écrire pour avoir son avis...


--
Michel Michaud mm@gdzid.com
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/

10 réponses

1 2 3
Avatar
Gabriel Dos Reis
"Michel Michaud" writes:

| Il me semble que James a déjà démontré par des articles de la norme,
| que vector<>::size_type ne peut pas être différent de size_t. Je me
| trompe ?

Je ne me souviens pas. Je ne vois pas ce qui l'empêche d'être un
unsigned int, même si size_t est un unsigned long.

| Est-il alors « correct » d'écrire :
|
| vector<TypeQuelconque> v;
| ...
| for (size_t i= 0; i != v.size(); ++i)
| ...
|
| Je trouve difficile d'introduire vector::size_type rapidement.

| Surtout lorsque les vecteurs contiennent des types personnels :
|
| for (vector<TypeQuelconque>::size_type i= 0; i != v.size(); ++i)
|
| C'est terriblement lourd, il me semble. Au point où il apparaît
| qu'un typedef (pour vector<TypeQuelconque>::size_type) serait très
| utile. Mais est-ce raisonnable de faire un typedef pour chaque type

Yep.

typedef vector<T>::size_type index_type;

| de vector (dans bien des programmes, il en faudrait un pour
| vector<int>::size_type, un autre pour vector<double>::size_type,
| etc.) si size_t fera l'affaire dans tous les cas ?

C'est possible.

vector<>::size_type est une des abstractions excessives, malheureuses
de la bibliothèque standard.

[...]

| L'emploi de valeurs non signées comme indice n'est pas sans
| problème non plus, car il est assez fréquent qu'un indice serve
| dans un calcul mettant en scène des valeurs signées. Là encore,

Yep, l'emploi des unsigned comme indices dans la bibliothèque standard
est quelque chose de regretable.

[...]

| N.B. BS utilise normalement int dans TC++PL... Je crois que je
| vais lui écrire pour avoir son avis...

Yep. Je crois que quelque part dans ce bouquin, il dit aussi ce qu'il
pense de l'emploi des unsigned ;-)

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote in message
news:...
"Michel Michaud" writes:

| Il me semble que James a déjà démontré par des articles de la norme,
| que vector<>::size_type ne peut pas être différent de size_t. Je me
| trompe ?

Je ne me souviens pas. Je ne vois pas ce qui l'empêche d'être un
unsigned int, même si size_t est un unsigned long.


Moi non plus. En fait, il y a deux questions : dans le cas général, il
me semble clair -- rien n'empêche d'écrire un allocateur avec un
size_type char, si cela t'enchante. En revanche, la norme exige bien que
le size_type de l'allocateur standard soit size_t. Reste la question si
le size_type de std::vector doit être identique au size_type de son
allocateur. Logiquement, je m'attendrais que si, mais je ne suis pas sûr
que la norme l'exige.

| Est-il alors « correct » d'écrire :

| vector<TypeQuelconque> v;
| ...
| for (size_t i= 0; i != v.size(); ++i)
| ...

| Je trouve difficile d'introduire vector::size_type rapidement.


Avec vi et compatibles :
:ab st std::vector<>::size_type
Par la suite, il faut retourner en arriére pour insérer le type
utilisateur. Mais ça aussi, on peut l'automatiser en partie.

Mais évidemment, ça n'est qu'une partie du problème. Le code est plus
facile à lire si les lignes ne sont pas excessivement longues non plus.
Et que les coupures de lignes ne viennent pas au milieu des expressions.

[...]
vector<>::size_type est une des abstractions excessives, malheureuses
de la bibliothèque standard.


Est-ce qu'on ne pourrait pas dire cela des allocateurs en général ?

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote in message
| news:...
| > "Michel Michaud" writes:
|
| > | Il me semble que James a déjà démontré par des articles de la norme,
| > | que vector<>::size_type ne peut pas être différent de size_t. Je me
| > | trompe ?
|
| > Je ne me souviens pas. Je ne vois pas ce qui l'empêche d'être un
| > unsigned int, même si size_t est un unsigned long.
|
| Moi non plus. En fait, il y a deux questions : dans le cas général, il
| me semble clair -- rien n'empêche d'écrire un allocateur avec un
| size_type char, si cela t'enchante. En revanche, la norme exige bien que
| le size_type de l'allocateur standard soit size_t. Reste la question si
| le size_type de std::vector doit être identique au size_type de son
| allocateur. Logiquement, je m'attendrais que si, mais je ne suis pas sûr
| que la norme l'exige.

La norme ne l'exige pas. Tout ce qu'elle dit c'est que c'est un
unsigned qui peut représenter les valeurs positives de
vector<>::difference_type -- qui lui même mesure la distance algébrique
entre deux itérateurs sur un vecteur, et un vector<T*>::iterator n'est
pas obligé à être un T*. Si on veut ête minimaliste, on peut dire que
c'est un type entier qui peut représenter
vector<>::allocator_type::max_size() / sizeof (T).

Dans la pratique, je ne sais pas s'il y a beaucoup d'implémentations
qui se compliquent la vie avec ce minimalisme.

-- Gaby
Avatar
Michel Michaud
Dans news:, Gabriel Dos
"Michel Michaud" writes:

Il me semble que James a déjà démontré par des articles de la
norme, que vector<>::size_type ne peut pas être différent de
size_t. Je me trompe ?


Je ne me souviens pas. Je ne vois pas ce qui l'empêche d'être un
unsigned int, même si size_t est un unsigned long.


Est-ce que l'inverse est possible ? La vraie question est de
savoir si je peux utiliser size_t pour les indices des vecteurs.
Comme je le demandais juste après :

Est-il alors « correct » d'écrire :

vector<TypeQuelconque> v;
...
for (size_t i= 0; i != v.size(); ++i)
...

Je trouve difficile d'introduire vector::size_type rapidement.



Alors qu'il serait facile dire que size_t est le type des indices
des vecteurs...

Surtout lorsque les vecteurs contiennent des types personnels :

for (vector<TypeQuelconque>::size_type i= 0; i != v.size(); ++i)

C'est terriblement lourd, il me semble. Au point où il apparaît
qu'un typedef (pour vector<TypeQuelconque>::size_type) serait très
utile. Mais est-ce raisonnable de faire un typedef pour chaque type


Yep.

typedef vector<T>::size_type index_type;


template typedef ? :-)

N.B. BS utilise normalement int dans TC++PL... Je crois que je
vais lui écrire pour avoir son avis...


Yep. Je crois que quelque part dans ce bouquin, il dit aussi ce
qu'il pense de l'emploi des unsigned ;-)


On peut bien dire ce qu'on veut, mais le C++ est le C++ et quand
on l'enseigne on ne peut pas passer à côté des choses qu'on
n'aime pas. Qu'enseignez-vous à vos élèves à College Station ?
À mettre int et à ne pas tenir compte des « warning » ? On peut
choisir notre compilateur (ou ses options) pour ne pas avoir les
avertissements, mais alors on ne fait pas du C++ très propre...

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


Avatar
Michel Michaud
Dans news:,
Gabriel Dos Reis wrote in message
news:...
"Michel Michaud" writes:

Je trouve difficile d'introduire vector::size_type rapidement.



Avec vi et compatibles :
:ab st std::vector<>::size_type
Par la suite, il faut retourner en arriére pour insérer le type
utilisateur. Mais ça aussi, on peut l'automatiser en partie.


La difficulté n'est pas de le taper, mais de le justifier ou de
l'expliquer aux débutants...

Mais évidemment, ça n'est qu'une partie du problème. Le code est
plus facile à lire si les lignes ne sont pas excessivement longues
non plus. Et que les coupures de lignes ne viennent pas au milieu
des expressions.


Dans une boucle for avec size_type, la déclaration de la variable
de contrôle prend en effet beaucoup de place et presque toute la
place !

Dans la pratique James, tu écris quoi ?

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/



Avatar
Gabriel Dos Reis
"Michel Michaud" writes:

| Dans news:, Gabriel Dos
| > "Michel Michaud" writes:
| >
| >> Il me semble que James a déjà démontré par des articles de la
| >> norme, que vector<>::size_type ne peut pas être différent de
| >> size_t. Je me trompe ?
| >
| > Je ne me souviens pas. Je ne vois pas ce qui l'empêche d'être un
| > unsigned int, même si size_t est un unsigned long.
|
| Est-ce que l'inverse est possible ?

Oui. Mais cela ne te dit rien sur ce qu'il est. C'est pour ça qu'ils
l'ont appelé une abstraction.

| La vraie question est de
| savoir si je peux utiliser size_t pour les indices des vecteurs.
| Comme je le demandais juste après :

Je crois que j'ai répondu que « int » est l'indice naturel, même si la
norme, dans ses excès d'abstraction, utilise xxx::size_type.

Est-ce que tu utilises

v[vector<T>::size_type(2)]

ou simplement

v[2];

[...]

| >> N.B. BS utilise normalement int dans TC++PL... Je crois que je
| >> vais lui écrire pour avoir son avis...
| >
| > Yep. Je crois que quelque part dans ce bouquin, il dit aussi ce
| > qu'il pense de l'emploi des unsigned ;-)
|
| On peut bien dire ce qu'on veut, mais le C++ est le C++ et quand

Personne ne dit le contraire.

| on l'enseigne on ne peut pas passer à côté des choses qu'on
| n'aime pas. Qu'enseignez-vous à vos élèves à College Station ?

Nous leur enseignons la programmation (et non C++) :-)
Nous utilisons C++, mais nous allons rapidement à l'essentiel des
concepts. Par exemple, le prochain cours (4ième) sera sur les
exceptions. Nous en avons besoin pour les introduire assez tôt à la
gestion des erreurs.
En particulier, pour les cours nous utilisons des entêtes qui
encapsulent certains détails inintéressants ; les accès aux tableaux
sont vérifiés par défaut (le contraire de ce que tu as dans la
bibliothèque standard).

| À mettre int et à ne pas tenir compte des « warning » ? On peut
| choisir notre compilateur (ou ses options) pour ne pas avoir les
| avertissements, mais alors on ne fait pas du C++ très propre...

Je le transmettrai à qui de droit :-)

-- Gaby
Avatar
Michel Michaud
Dans news:, Gabriel Dos
"Michel Michaud" writes:

Dans news:, Gabriel Dos
"Michel Michaud" writes:

Il me semble que James a déjà démontré par des articles de la
norme, que vector<>::size_type ne peut pas être différent de
size_t. Je me trompe ?


Je ne me souviens pas. Je ne vois pas ce qui l'empêche d'être un
unsigned int, même si size_t est un unsigned long.


Est-ce que l'inverse est possible ?


Oui. Mais cela ne te dit rien sur ce qu'il est. C'est pour ça qu'ils
l'ont appelé une abstraction.


Mais ça me dit que size_t n'est pas sûr. C'est beaucoup !

La vraie question est de
savoir si je peux utiliser size_t pour les indices des vecteurs.
Comme je le demandais juste après :


Je crois que j'ai répondu que « int » est l'indice naturel, même si
la norme, dans ses excès d'abstraction, utilise xxx::size_type.


Un indice naturel qui peut ne pas fonctionner et/ou donner des
avertissements des « bons » compilateurs !

:-(


Est-ce que tu utilises

v[vector<T>::size_type(2)]

ou simplement

v[2];


Ni l'un ni l'autre ! À part [0], je ne me rappelle pas quand
j'ai utilisé une constante comme indice, sinon j'opterais
probablement pour

v[static_cast<std::vector<T>::size_type>(2)]

Tant qu'à y être ! :-)

Plus sérieusement, si v.size() > 100000, je sais que je peux
faire v[100000]= 0;, mais rien ne me dit que je peux faire
int i0000; v[i]= 0;. Par contre, je peux faire i5000;
v[i]= 0;, n'est-ce pas ? Brrrr....

n'aime pas. Qu'enseignez-vous à vos élèves à College Station ?


Nous leur enseignons la programmation (et non C++) :-)


Moi aussi. Et si jamais, on me démontre qu'il y a trop de
problème pour ce que soit un bon outil, je vais penser à en
changer ! Ce n'est pas mon intention pour le moment, les
avantages me paraissent toujours supérieurs...

Nous utilisons C++, mais nous allons rapidement à l'essentiel des
concepts. Par exemple, le prochain cours (4ième) sera sur les
exceptions. Nous en avons besoin pour les introduire assez tôt à la
gestion des erreurs.
En particulier, pour les cours nous utilisons des entêtes qui


(en-tête Gabriel, en-tête... :-)

encapsulent certains détails inintéressants ; les accès aux tableaux
sont vérifiés par défaut (le contraire de ce que tu as dans la
bibliothèque standard).


Moi aussi v[i] est vérifié. Mais vous utilisez std::vector ou non ?
Tu ne m'as pas dit explicitement de quel type tu déclares les
indices (je suppose que c'est int...).

À mettre int et à ne pas tenir compte des « warning » ? On peut
choisir notre compilateur (ou ses options) pour ne pas avoir les
avertissements, mais alors on ne fait pas du C++ très propre...


Je le transmettrai à qui de droit :-)


J'ai toujours dit que, dans le doute, je préfère choisir de faire
comme BS, car ça me donne un justification assez sérieuse. Ceci dit,
c'est Koenig qui fait un peu référence pour les livres d'introduction
et il utilise size_type... En plus, depuis que VC peut compiler du
code conforme sans avertissement en mettant le niveau le plus élevé
d'avertissements, j'aimerais pouvoir mettre ce niveau, qui détecte
plusieurs petites erreurs utiles... Malheureusement, ce niveau n'aime
pas tellement les conversions signed/unsigned implicites...

Je crois qu'on est d'accord cependant : l'erreur est d'avoir introduit
les unsigned dans les vector comme indice. Ça donne vraiment peu
d'avantages quand on compare aux autres difficultés...

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/




Avatar
Loïc Joly
Gabriel Dos Reis wrote:
| La vraie question est de
| savoir si je peux utiliser size_t pour les indices des vecteurs.
| Comme je le demandais juste après :

Je crois que j'ai répondu que « int » est l'indice naturel, même si la
norme, dans ses excès d'abstraction, utilise xxx::size_type.

Est-ce que tu utilises

v[vector<T>::size_type(2)]

ou simplement

v[2];


Ca me fait poser une question : Dans la norme, je lis que
vector<T>::size_type est un unsigned integral type. Est-ce que ça veut
dire qu'il fait forcément partie de l'ensemble {unsigned char, unsigned
short, unsigned int, unsigned long int}, ou est-ce qu'il pourraît être
défini comme un type utilisateur ou un type extention du compilateur ?

--
Loïc

Avatar
Gabriel Dos Reis
Loïc Joly writes:

| Gabriel Dos Reis wrote:
| > | La vraie question est de
| > | savoir si je peux utiliser size_t pour les indices des vecteurs.
| > | Comme je le demandais juste après :
| > Je crois que j'ai répondu que « int » est l'indice naturel, même si
| > la
| > norme, dans ses excès d'abstraction, utilise xxx::size_type.
| > Est-ce que tu utilises
| > v[vector<T>::size_type(2)]
| > ou simplement
| > v[2];
|
| Ca me fait poser une question : Dans la norme, je lis que
| vector<T>::size_type est un unsigned integral type. Est-ce que ça veut
| dire qu'il fait forcément partie de l'ensemble {unsigned char,
| unsigned short, unsigned int, unsigned long int}, ou est-ce qu'il
| pourraît être défini comme un type utilisateur ou un type extention du
| compilateur ?

Avec la définition de C90 (qui est celle incluse dans C++), cela fait
forcément partie de l'ensemble que tu as énuméré. Si C++ évoluait pour
adopter la définition de C99, alors cela pourrait être un type
extension du compilateur.

-- Gaby
Avatar
Gabriel Dos Reis
"Michel Michaud" writes:

[...]

| Plus sérieusement, si v.size() > 100000, je sais que je peux
| faire v[100000]= 0;, mais rien ne me dit que je peux faire
| int i0000; v[i]= 0;. Par contre, je peux faire i5000;
| v[i]= 0;, n'est-ce pas ? Brrrr....

Ou tu peux aussi faire v.at(i) :-)

[...]

| > encapsulent certains détails inintéressants ; les accès aux tableaux
| > sont vérifiés par défaut (le contraire de ce que tu as dans la
| > bibliothèque standard).
|
| Moi aussi v[i] est vérifié. Mais vous utilisez std::vector ou non ?

Avant qu'il deviennent « mûrs », ils utilises « vector » -- sans
qualification.

| Tu ne m'as pas dit explicitement de quel type tu déclares les
| indices (je suppose que c'est int...).

for (int i = 0; i < N; ++i)
v[i] = xxxx;

| >> À mettre int et à ne pas tenir compte des « warning » ? On peut
| >> choisir notre compilateur (ou ses options) pour ne pas avoir les
| >> avertissements, mais alors on ne fait pas du C++ très propre...
| >
| > Je le transmettrai à qui de droit :-)
|
| J'ai toujours dit que, dans le doute, je préfère choisir de faire
| comme BS, car ça me donne un justification assez sérieuse. Ceci dit,

Il est cohérent avec ce qu'il écrit dans son bouquin :-)

(et je crois que la formulation de sa pensée dans le bouquin est
nettement supérieure à ce que je pourrais dire sur son compte ici ;-p)

| c'est Koenig qui fait un peu référence pour les livres d'introduction
| et il utilise size_type... En plus, depuis que VC peut compiler du
| code conforme sans avertissement en mettant le niveau le plus élevé
| d'avertissements, j'aimerais pouvoir mettre ce niveau, qui détecte
| plusieurs petites erreurs utiles... Malheureusement, ce niveau n'aime
| pas tellement les conversions signed/unsigned implicites...

Ben dans ce cas, utilises std::size_t.

| Je crois qu'on est d'accord cependant : l'erreur est d'avoir introduit
| les unsigned dans les vector comme indice. Ça donne vraiment peu
| d'avantages quand on compare aux autres difficultés...

Yep.

-- Gaby
1 2 3