OVH Cloud OVH Cloud

Contigüité des éléments d'un `std::vector´

167 réponses
Avatar
drkm
Je viens de tomber sur un message de Michel, d'il y a un mois, dont
voici un extrait :

> From: "Michel Michaud" <mm@gdzid.com>
> Subject: Re: buffer et std::vector<char> passage de l'un a l'autre
> Message-ID: <pQnHa.816$5d.225371@news20.bellglobal.com>
> Date: Mon, 16 Jun 2003 14:16:52 -0400

> Avec

> vector<char> v(taille);

> &v[0] est un char* qui peut être passé aux fonctions attendant un
> char[]/char*. La norme ne dit pas explicitement que les char sont
> contigus, mais c'est un fait et il y a une correction à la norme qui
> l'indique aussi.

J'avais toujours entendu dire que la contigüités des éléments d'un
vecteur était garantie. Apparemment non. Pour ce qui est de la
correction à la norme, je suppose que tu parlais d'un DR. En as-tu la
référence, stp ?

--drkm

10 réponses

Avatar
Gabriel Dos Reis
"Christophe Lephay" writes:

| "Gabriel Dos Reis" a écrit dans le message de
| news:
| > "Christophe Lephay" writes:
| >
| > | Dans le deuxième cas, quand on voit avec quel soin (pointillisme ?)
| chaque
| > | mot est discuté pendant de nombreuses heures par le comité (à ce qu'il
| > | semble), on voit mal comment celà aurait pu passer à travers et être
| oublié.
| >
| > alors pourquoi le comité a-t-il mis enplace le processus de DR ?
|
| Quel rapport ?

Le voici :

Ce n'est pas parce que le comité passe des heures, des mois ou des
années à discuter (pinailler ?) des mots et des points dans les
formulations que des idées (discutées explicitement, ou
implicitement dans les têtes) ne passent pas la forme finale.
Si le comité avait pensé que les soins qu'il apportait à la
rédaction des clauses suffisaient à endiguer ce genre de source de
defauts, il n'aurait pas mis en place le processus de DR (en tout,
je me souviens très distinctements des explications données par
Beman lorsu'il a la première fois expliqué le processus -- Valentin
a encore les croquis s'il n'a pas brûlé sa machine).

Un simple cas (parmi d'autres) me vient à l'esprit, regarde la
note de John Spicer dans Core Issue #400
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#400

En fait il n'est pas rare de voir des DRs pour lesquels, la
discussion tourne autour de « what was the intent » et ce qui est
effectivement écrit et qu'on se rende compte de l'erreur (mismatch
entre l'intention et ce qui est écrit plus tard). Name lookup tient
un bon lot dans le Core, et les streams dans la Library.

Jusqu'à présent, dans ces cas je n'ai vu personne de responsable dans
le comité affirmer que l'intention était une invention pour faire
passer quelque chose.

| La question (assez peu interessante d'un point de vue
| concret, du reste) est si l'intention du comité était de faire de la
| contiguité des éléments de vector quelque chose d'obligatoire ou de le
| considérer comme quelque chose relevant de l'implémentation, pourvu que soit
| fourni un moyen d'assurer la compatibilité avec le C.

si les tableaux C sont contigus et qu'on veut que std::vector soit
compatibles avec eux, tu connais d'autres moyens que de garantir la
contigüité ?

| > | Je trouve le premier cas plus crédible,
| >
| > Je trouve surtout que ces deux catégorisations reflètent une ignorance
| > profonde du processus de normalisation, en tout cas dans WG21.
|
| Bien que je trouve ta remarque un peu sentencieuse (comme si le fait que tu
| trouves ceci ou celà était suffisant en soi et ne nécessitait pas que tu
| argumentes), je t'accorde d'autant plus le fait que que je n'y connaisse
| effectivement pas grand chose que j n'y suis pas particulièrement interessé
| (ce qui ne veut pas dire que je n'y sois particulièrement pas interessé)...

Ce que j'ai voulu dire c'est que ces catégorisations sont à des
années-lumière de comment le processus fonctionne.

-- Gaby
Avatar
Alain Naigeon
"Gabriel Dos Reis" a écrit dans le message
news:
"Alain Naigeon" writes:

| en fin de fonction je peux, mais je ne dois pas,
| retourner un pointeur sur une variable de pile, qui n'existe plus ;

Pas tout à fait. Tu peux retourner un pointeur sur une variable locale.
Ce que la norme dit, c'est que si c'est utilisé le fonctionnement est
indéfini. Cela ne veut pas dire que tu ne dois pas. Cela veut dire
simplement que la norme n'impose aucune restriction sur la sémantique
de ton programme. Ton compilateur peut choisir de définir ce
fonctionnement ou non.


D'accord. On me permet de faire une chose dont on est au moins
sûr à l'avance qu'elle est soit incorrecte, soit non portable. Tu défends
cela, vraiment ?


C'est tout comme « tant d'exemples » ?


Tout récemment quelqu'un a remarqué qu'on peut déréférencer
un pointeur non initialisé. Note bien qu'il a dit un pointeur, il n'a
pas dit un pointeur volatile...

Dois-je en conclure que Stroustrup ou Koenig ne font pas parties de
ces « gens célèbres » ? Ce serait dommage, lorsqu'il s'agit de C++.


Je lis dans Stroustrup, 2ème édition française, page 10, une mise en garde
contre les données membres publiques (mais dans certaines circonstances,
j'ajoute, pour être honnête).

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France

Avatar
Alain Naigeon
"Gabriel Dos Reis" a écrit dans le message
news:

[...]

Je ne retrouve plus le passage, mais tu me mettais au défi
d'exprimer syntaxiquement la contiguïté dans une interface
en C++.
Justement, j'arrivais par moi-même à la conclusion suggérée
par ta question malicieuse...
Maintenant, dis-moi : cette impossibilité est-elle une intuition
de ta part, ou bien une induction basée sur un grand nombre
de tentatives (!), ou bien encore un théorème ? Et dans ce
dernier cas, dans quel cadre conceptuel, mathématique
ou autre, ses hypothèses et sa démonstration peuvent-elles
être exprimées rigoureusement ?
Ca ne paraît pas évident comme théorème, déjà parce que
ça suppose qu'on sache définir exactement ce qu'on appelle
une syntaxe !

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France
Avatar
Alain Naigeon
"Gabriel Dos Reis" a écrit dans le message
news:

"Alain Naigeon" writes:

| "Jean-Marc Bourguet" a écrit dans le message news:
| >
| > Le fait de passer un indice de ligne ou un indice de colonne est
| > attendu est une erreur de typage en Pascal (ou en Ada) bien programme.
|
| J'aurais voulu pouvoir dire ça de façon aussi claire et concise !

Si c'est ce que tu as voulu dire, la même chose (erreur de
compilation) est possible en C++/

| Mais puisqu'il faut que je tartine du code pour avoir le droit de
| le dire, eh bien, je vais tartiner :-)

:-)


Oui, c'est tout à fait ce que je voulais dire, sans tricher.
Alors voilà :

class Coord
{
public :
int valeur( ) { return val ; }
void valeur( int i ) { if( ok( i ) ) val = i ; }

protected :
Coord( int i ) { val = ok( i ) ? i : valdefaut ; }
bool ok( int i ) { return i >= valmin && i <= valmax ; }
int val ;
static int valmin, valmax, valdefaut ;

} ;

int Coord::valmin = 1 ;
int Coord::valmax = 8 ;
int Coord::valdefaut = 1 ;

class Ligne : public Coord
{
public :
Ligne( int i ) : Coord( i ) { }
} ;

class Colonne : public Coord
{
public :
Colonne( int i ) : Coord( i ) { }
} ;


Il n'y a presque rien dans Ligne et Colonne, elles ne sont là
que pour obtenir une erreur à la compilation si je permute
les deux coordonnées :

int test_compil( Ligne l, Colonne c )
{
return 1 ;
}

test_compil( Ligne( 5 ), Colonne ( 7 ) ) ; // ok
Colonne x( 5 ) ;
Ligne y( 4 ) ;
test_compil( x, y ) ; // erreurs, évidemment.
// (type mismatch et conversion impossible)

(et là je pourrais m'exclamer aussi, comme sur la page
que tu as donnée en lien pour auto_ptr : "AND THAT'S GREAT")

Si ça te fait rire, sache que ça m'arrive souvent, ce genre
de blague, parce j'ai tendance à ordonner les choses
différemment selon le nom que je leur donne :
ligne, colonne
ou abcisse, ordonnée ou x, y

Je ne suis pas célèbre, et ma devise à moi c'est plutôt :
"any potential error will, sooner or later, become an actual one"
:-)
Je n'ai pas de preuve formelle, mais au moins des indices
sérieux qui seraient pas mal HS (du genre : "tout ce qui peut
arriver finit par arriver un jour, sauf peut-être pour un ensemble
de cas de mesure nulle, restreint aux points {"Stroustrup",
"Clamage", et al}")

Bon, maintenant, ma question, sérieuse, c'était évidemment :
y a-t-il en C++ une façon plus concise que ci-dessus d'obtenir un
diagnostic dès la compilation ?

...

M'enfin, oser écrire "a potential error is not an error in C++",
c'est énorme, les bras m'en tombent, et c'est évidemment
le *contraire* de ce que j'attends d'un langage ! On devrait
afficher cette phrase en gros caractères sur les murs de plein
de bureaux : celui du type qui embauche les gens, celui qui
les paie, celui qui provisionne le poste budgétaire "pénalités",
et celui qui essaie de vendre des lancements Ariane i avec i > 4.

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France

Avatar
Christophe Lephay
"Gabriel Dos Reis" a écrit dans le message de
news:
Ce n'est pas parce que le comité passe des heures, des mois ou des
années à discuter (pinailler ?) des mots et des points dans les
formulations que des idées (discutées explicitement, ou
implicitement dans les têtes) ne passent pas la forme finale.


Je n'ai jamais dit celà, au contraire même, puisque je disais qu'il me
paraissait peu probable que le comité avec le (limite)pointillisme dont il
semble faire preuve ait laissé passé la contiguité de vector si c'était un
point qu'il considérait important.

Si le comité avait pensé que les soins qu'il apportait à la
rédaction des clauses suffisaient à endiguer ce genre de source de
defauts, il n'aurait pas mis en place le processus de DR (en tout,
je me souviens très distinctements des explications données par
Beman lorsu'il a la première fois expliqué le processus -- Valentin
a encore les croquis s'il n'a pas brûlé sa machine).


Par "ce genre de source de défaut", tu veux dire l'oubli de spécifications
qui sont pourtant des intentions avérées du comité ?

si les tableaux C sont contigus et qu'on veut que std::vector soit
compatibles avec eux, tu connais d'autres moyens que de garantir la
contigüité ?


Une solution comme celle proposée pour les string ? Soit une fonction
data(), soit un opérateur de conversion...
C'est bien entendu la solution d'éléments nativement contigues qui est la
plus efficace (en terme de vitesse), mais j'imagine que d'autres solutions
sont du domaine du possible. On en revient alors à l'intention du comité
d'alors. Si son intention était réellement d'imposer une telle contiguité,
ce ne peut être que pour des raisons d'efficacité (ce qui est un peu
inhabituel, à ce que je me suis laissé dire, de la part de la norme que
d'imposer une implémentation pour des raisons de performance). Peut-être,
d'ailleurs, est-ce la raison pour laquelle elle aurait été sous-entendue, au
lieu d'être réellement oubliée ?

Bien entendu, ce ne sont que des spéculations, des hypothèses que j'estime
plus ou moins plausibles en fonctions des informations qui m'arrivent. Si
les gens du comité de l'époque m'affirmait qu'ils avaient telle ou telle
intention, je n'aurais aucune raison de ne pas les croire...

Ce que j'ai voulu dire c'est que ces catégorisations sont à des
années-lumière de comment le processus fonctionne.


Je ne vois pas en quoi. Ceci dit, c'est toujours après coup qu'il est
possible de "catégoriser", car c'est généralement beaucoup moins structuré
dans le feu de l'action (ce n'est pas spécifique aux comités de
normalisation), et je reconnais que de telles catégorisations peuvent
sembler un peu artificielles (mais le sont-elles vraiment, c'est une autre
question) lorsqu'on les compare avec l'impression qu'on a pu ressentir dans
le feu de l'action...

Chris

Avatar
Christophe Lephay
a écrit dans le message de
news:
Seulement, voilà, être explicit exige une expression. Qu'on en cache
l'expression, pour des raisons politiques ou d'autres, ça peut arriver.
Mais je ne vois pas une telle raison ici.


Peut-être parce que celà ressort du domaine de la performance, et que c'est
inhabituel de la part du comité que d'imposer une implémentation pour des
raisons de performance (c'est une idée qui m'est venue en écrivant un autre
post)

Sans vouloir offenser -- il y a dans la culture française une tendance à
chercher trop dans des mots individuels, sans prendre en considération
le tout. Gaby en souffre, mais j'ai bien vu le cas par ailleurs. C'est
une des choses, d'ailleurs qui rend la revue du code plus difficile en
France qu'ailleurs. L'auteur prend trop en compte comment celui qui fait
la revue a formulé sa critique, et pas assez le simple fait -- il y a
une erreur, ou le code n'est pas conforme aux régles. Simple fait qui
n'est pas un insulte ni une critique personnelle.


Ce qui est certain, c'est que les français sont très individualistes, et
prennent de ce fait souvent les critiques comme quelque chose de personnel
au lieu d'y voir l'avantage au niveau plus global, au niveau du groupe ou de
l'entreprise...

En anglais, je dirais que « you don't see the forest for the trees »


On dit un peu la même chose en français : "c'est l'arbre qui cache la
foret".

Probablement. Il n'y a qu'en France qu'on s'acharne sur un simple mot
comme ça:-).


Je ne sais pas si on peut généraliser à la nation toute entière, bien qu'il
semble effectivement fréquent (mais je ne peux pas dire si c'est plus ou
moins qu'ailleurs) de prendre une critique ou une remarque comme une attaque
ou une remise en question personnelle...

Chris

Avatar
Gabriel Dos Reis
"Alain Naigeon" writes:

| "Gabriel Dos Reis" a écrit dans le message
| news:
|
| [...]
|
| Je ne retrouve plus le passage, mais tu me mettais au défi
| d'exprimer syntaxiquement la contiguïté dans une interface
| en C++.
| Justement, j'arrivais par moi-même à la conclusion suggérée
| par ta question malicieuse...

en fait, je ne la voulais pas malicieuse :-)

| Maintenant, dis-moi : cette impossibilité est-elle une intuition
| de ta part, ou bien une induction basée sur un grand nombre
| de tentatives (!), ou bien encore un théorème ?

Sur une constatation très simple : la sémantique, c'est la partie qui
s'occupe de donner un sens aux mots, i.e à la syntaxe.
Chaque fois que j'ai une notation, il faut que je lui donne un sens.

| Et dans ce
| dernier cas, dans quel cadre conceptuel, mathématique
| ou autre, ses hypothèses et sa démonstration peuvent-elles
| être exprimées rigoureusement ?

Ben j'avoue que je ne comprends pas très bien où tu veux en venir.
Si j'écris

int volatile i;

si je ne dis paa la signification de volatile, la syntaxe ne suffit
pas pour savoir comment se comporte i. C'est pareil pour

int* p = new int[90];

si je n'ai pas une description sémantique supplémentaire sur operator
new, je ne peux affirmer que « p » pointe sur une zone contigüe.
La syntaxe n'est là que pour temoigner des idées (i.e. sémantiques)..

| Ca ne paraît pas évident comme théorème, déjà parce que
| ça suppose qu'on sache définir exactement ce qu'on appelle
| une syntaxe !

En théorie des langages, ce n'est pas un problème.
Avatar
Gabriel Dos Reis
"Alain Naigeon" writes:


[...]

| et celui qui essaie de vendre des lancements Ariane i avec i > 4.

au fait, le module « fautif » d'ariane 5 n'est pas écrit en C++, mais dans
un langage dit sécuritaire. Mais en fait, le module n'était pas
fautif : il faisait exacteemnt et très bien ce pourquoi il a été conçu.
Le point est que dans le développement de logiciels, le langage de
programmation ne peut résoudre tous les problèmes de management.

-- Gaby
Avatar
Gabriel Dos Reis
"Alain Naigeon" writes:

| Oui, c'est tout à fait ce que je voulais dire, sans tricher.
| Alors voilà :
|
| class Coord
| {

[...]

| class Ligne : public Coord

[...]

| class Colonne : public Coord

Ma question naturelle est pourquoi tu écris ça ?

[...]

| Bon, maintenant, ma question, sérieuse, c'était évidemment :
| y a-t-il en C++ une façon plus concise que ci-dessus d'obtenir un
| diagnostic dès la compilation ?

template<typename T, int m, int M>
struct Coordinate {
explicit Coordinate(int i) : value(validate(i)) { }

int to_int() const { return value; }

Coordinate& operator=(int i)
{ return *this = Coordinate(i); }

private:
int value;

static int validate(int i)
{
return i >= m && i <= M ? i : throw std::range_error("looser");
}
};

struct line_tag { };
struct column_tag { };

typedef Coordinate<line_tag, 1, 8> Line;
typedef Coordinate<column_tag, 1, 8> Column;


-- Gaby
Avatar
Alain Naigeon
"Gabriel Dos Reis" a écrit dans le message
news:

"Alain Naigeon" writes:

| Oui, c'est tout à fait ce que je voulais dire, sans tricher.
| Alors voilà :
|
| class Coord
| {

[...]

| class Ligne : public Coord

[...]

| class Colonne : public Coord

Ma question naturelle est pourquoi tu écris ça ?

[...]


Sans aucun doute parce que je n'imaginais pas
ce qui suit... :


template<typename T, int m, int M>


[...]

Oui, c'est plus concis, compte tenu du fait
que c'est bien plus général.

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France