OVH Cloud OVH Cloud

Fstream n'en fais qu a ca tete : pb de link

13 réponses
Avatar
NonoSoft
Voici mon post : http://www.developpez.net/forums/viewtopic.php?t=103975

On m'a dis d'ecrire ici pour avoir peu etre une réponse.

3 réponses

1 2
Avatar
Gabriel Dos Reis
writes:

| > Alors <fstream> peut, de manière interne, n'inclure que ces entêtes
| > (internes) avec le résultat qu'il n'a pas à inclure l'intégralité de
| > <istream> ou <ostream> dans <fstream>.
|
| Selon la norme, std::istream est défini dans <istream>, et non ailleurs.

Yep. Mais la norme n'immpose pas à l'implémentation comment elle doit
faire pour disposer de la définitonde std::istream là où elle en a
besoin.
De fait, nous avons fait quelque chose comme ça pour std::char_traits
-- la seule manière pour l'utilisateur de l'avoir c'est d'inclure
<string> ; mais l'implémentation peut faire autement. Récemment nous
avons changé les dépendances pour d'autres raisons.

| La norme donne le droit à une implémentation d'inclure d'autres en-têtes
| standard depuis un en-tête standard.

Tout à fait -- mais l'implémentation peut s'en passer, et ce n'est pas
de la spéculation.

| Elle ne lui donne pas le droit à faire n'importe quoi.

Qu'est-ce que ça veut dire ici « n'importe quoi » ?

| Si j'inclus <iostream>, ou <fstream>, je ne sais
| pas d'office (d'après la norme) si <istream> a été inclu.

Exact.

| Mais si std::istream est défini, je sais (d'après la norme) que
| <istream> a été inclu,

Bah non. La norme ne dit pas ça.

| et que donc les autres opérateurs << définis dans <istream> sont
| disponibles. Ou bien, j'ai le contenu de <istream>, ou bien, je ne l'ai
| pas, mais je ne peux pas en avoir la moitié.

As-tu un programme conforme qui le détecte ?

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

| > Alors <fstream> peut, de manière interne, n'inclure que ces
| > entêtes (internes) avec le résultat qu'il n'a pas à inclure
| > l'intégralité de <istream> ou <ostream> dans <fstream>.

| Selon la norme, std::istream est défini dans <istream>, et non
| ailleurs.

Yep. Mais la norme n'immpose pas à l'implémentation comment elle doit
faire pour disposer de la définitonde std::istream là où elle en a
besoin.


Ça dépend de comment on l'interprète. En C, c'est clair. Un en-tête ne
peut introduire que les symboles décrits dans la norme pour cet en-tête
et les symboles dans l'espace de nommage réservé. La norme C++ donne à
l'implémentation le droit d'inclure d'autres en-têtes standard depuis un
en-tête standard, mais c'est tout. En dehors de ça, c'est comme en C.

De fait, nous avons fait quelque chose comme ça pour std::char_traits
-- la seule manière pour l'utilisateur de l'avoir c'est d'inclure
<string> ; mais l'implémentation peut faire autement. Récemment nous
avons changé les dépendances pour d'autres raisons.


Je sais que c'est ce que font toutes les implémentations. Tu as bien
besoin de char_traits pour istream et al. Mais on n'a pas envie
d'inclure tout de <string>. AMHA, on doit le permettre, et je crois que
l'intention était de le permettre (au moins que ce soit prendre mes
désirs pour la réalité). Mais en rélisant la norme, je trouve que, telle
que c'est écrite, on n'en a pas droit -- si char_traits est visible,
basic_string doit l'être aussi.

| La norme donne le droit à une implémentation d'inclure d'autres
| en-têtes standard depuis un en-tête standard.

Tout à fait -- mais l'implémentation peut s'en passer, et ce n'est pas
de la spéculation.


Certes. Dans <istream>, par exemple, l'implémentation peut inclure
<ios>, ou il peut utiliser de la magie du compilateur pour s'en passer,
bien que basic_ios soit une classe de base de istream. Je crois que
l'intention était aussi de permettre l'implémentation d'exposer la
définition de basic_ios sans avoir à inclure tout <ios>, mais ce n'est
pas ce qui est écrit. On ne dit pas qu'un en-tête peut définir ou
déclarer des symboles d'autres en-têtes -- on dit qu'il peut inclure
d'autres en-têtes. Ce n'est pas la même chose.

| Elle ne lui donne pas le droit à faire n'importe quoi.

Qu'est-ce que ça veut dire ici « n'importe quoi » ?


Quelque chose que la norme ne permet pas:-).

| Si j'inclus <iostream>, ou <fstream>, je ne sais pas d'office
| (d'après la norme) si <istream> a été inclu.

Exact.

| Mais si std::istream est défini, je sais (d'après la norme) que
| <istream> a été inclu,

Bah non. La norme ne dit pas ça.


La norme dit que std::istream est déclaré et défini dans <istream>. Pas
dans <iostream> (par exemple). Elle ne permet pas une définition
partielle.

| et que donc les autres opérateurs << définis dans <istream> sont
| disponibles. Ou bien, j'ai le contenu de <istream>, ou bien, je ne
| l'ai pas, mais je ne peux pas en avoir la moitié.

As-tu un programme conforme qui le détecte ?


Conforme, oui. Strictement conforme, non.

Dans l'ensemble, je ne crois pas que ça a de l'importance. L'exception
est <iostream> ; si j'ai des << membres, je veux aussi avoir les <<
non-membres défini dans <ostream>, c-à-d en gros : si j'utilise
<iostream>, et j'oublie <ostream>, je veux ou bien qu'il y a une erreur
de compilation, ou bien que ça marche correctement. Je ne veux pas que
le compilateur choisi un << inattendu parce qu'il n'y a qu'une moitié de
l'ensemble de surcharge visible.

Ce qui m'intéresse ici, c'est notre vieil ami :

#include <iostream>

int main()
{
std::cout << "Hello, world!n" ;
return 0 ;
}

Nous somme bien d'accord (je crois) que :
- ce programme n'est pas portable, au moins selon la norme, et
- une implémentation a le droit de le faire marcher.
La question que je me pose, c'est que si l'implémentation ne le fait pas
marcher, est-ce qu'un diagnostique est exigé ou non. Parce que si
l'implémentation, par un moyen quelconque, inclut la définition de
std::istream, sans inclure tout <istream> (c-à-d surtout, sans les
operator<< globaux), on aurait pas une erreur de compilation, mais un
changement de sémantique.

A priori, je ne vois pas d'autre cas où c'est un problème. Si on décide
que l'intention était que <iostream> inclut en fait <istream>,
<ostream>, <ios> et <streambuf>, le problème disparaît, ou au moins
devient purement théorique et sans intérêt. (Voilà donc une bonne raison
pour « inventer une intention », pour faire ce qu'on aurait peut-être dû
faire avant, mais auquel on n'a pas pensé.)

Et en lisant la norme soigneusement, sans préjugés sur ce que je sais
(ou crois savoir) des intentions, je trouve la garantie. Pas que ça
m'aide réelement, parce que les implémentations et la norme, ce sont
deux choses distinctes. Et je crois que la garantie, c'est réelement
accidentale, et non voulue. (Mais alors, pourquoi dire que l'en-tête
peut inclure d'autres en-têtes standard, plutôt que de simplement dire
qu'il peut définir et/ou déclarer des choses décrites dans d'autres
en-têtes ? Est-ce que le choix de mots est significatif d'une intention,
ou non ?)

--
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:...
| > writes:
|
| > | > Alors <fstream> peut, de manière interne, n'inclure que ces
| > | > entêtes (internes) avec le résultat qu'il n'a pas à inclure
| > | > l'intégralité de <istream> ou <ostream> dans <fstream>.
|
| > | Selon la norme, std::istream est défini dans <istream>, et non
| > | ailleurs.
|
| > Yep. Mais la norme n'immpose pas à l'implémentation comment elle doit
| > faire pour disposer de la définitonde std::istream là où elle en a
| > besoin.
|
| Ça dépend de comment on l'interprète. En C, c'est clair.

Il est question de C++ ici. <istream> est mandaté par la norme C?

| Un en-tête ne
| peut introduire que les symboles décrits dans la norme pour cet en-tête
| et les symboles dans l'espace de nommage réservé. La norme C++ donne à
| l'implémentation le droit d'inclure d'autres en-têtes standard depuis un
| en-tête standard, mais c'est tout. En dehors de ça, c'est comme en C.

La norme C++ est plus spécifique que cela.
|
| > De fait, nous avons fait quelque chose comme ça pour std::char_traits
| > -- la seule manière pour l'utilisateur de l'avoir c'est d'inclure
| > <string> ; mais l'implémentation peut faire autement. Récemment nous
| > avons changé les dépendances pour d'autres raisons.
|
| Je sais que c'est ce que font toutes les implémentations.

Ah bon ! Dans ce cas tu dois pouvoir nommer l'implémentation dont il
était question plus haut.

| Tu as bien
| besoin de char_traits pour istream et al. Mais on n'a pas envie
| d'inclure tout de <string>. AMHA, on doit le permettre, et je crois que
| l'intention était de le permettre (au moins que ce soit prendre mes
| désirs pour la réalité). Mais en rélisant la norme, je trouve que, telle
| que c'est écrite, on n'en a pas droit -- si char_traits est visible,
| basic_string doit l'être aussi.

La question est : as-tu un programme conforme qui détecte le contraire ?

| > | La norme donne le droit à une implémentation d'inclure d'autres
| > | en-têtes standard depuis un en-tête standard.
|
| > Tout à fait -- mais l'implémentation peut s'en passer, et ce n'est pas
| > de la spéculation.
|
| Certes. Dans <istream>, par exemple, l'implémentation peut inclure
| <ios>, ou il peut utiliser de la magie du compilateur pour s'en passer,
| bien que basic_ios soit une classe de base de istream. Je crois que
| l'intention était aussi de permettre l'implémentation d'exposer la
| définition de basic_ios sans avoir à inclure tout <ios>, mais ce n'est
| pas ce qui est écrit.

Oh, il est écrit qu'on peut faire comme on veut tant qu'on préserve le
fonctionnement observable.

| On ne dit pas qu'un en-tête peut définir ou
| déclarer des symboles d'autres en-têtes -- on dit qu'il peut inclure
| d'autres en-têtes. Ce n'est pas la même chose.

Qui parle de ça ? À part toi dans ce message, je ne vois personne d'autre.

| > | Elle ne lui donne pas le droit à faire n'importe quoi.
|
| > Qu'est-ce que ça veut dire ici « n'importe quoi » ?
|
| Quelque chose que la norme ne permet pas:-).
|
| > | Si j'inclus <iostream>, ou <fstream>, je ne sais pas d'office
| > | (d'après la norme) si <istream> a été inclu.
|
| > Exact.
|
| > | Mais si std::istream est défini, je sais (d'après la norme) que
| > | <istream> a été inclu,
|
| > Bah non. La norme ne dit pas ça.
|
| La norme dit que std::istream est déclaré et défini dans <istream>. Pas
v| dans <iostream> (par exemple).

Qui met cela en doute ?

| Elle ne permet pas une définition partielle.

Non, mais la question fondamentale est : as-tu un programme conforme
qui détecte la violation ?

| > | et que donc les autres opérateurs << définis dans <istream> sont
| > | disponibles. Ou bien, j'ai le contenu de <istream>, ou bien, je ne
| > | l'ai pas, mais je ne peux pas en avoir la moitié.
|
| > As-tu un programme conforme qui le détecte ?
|
| Conforme, oui. Strictement conforme, non.

"strictement conforme" n'est pas une notion C++.

| Dans l'ensemble, je ne crois pas que ça a de l'importance.

Ben voyons.

| L'exception
| est <iostream> ; si j'ai des << membres, je veux aussi avoir les <<
| non-membres défini dans <ostream>, c-à-d en gros : si j'utilise
| <iostream>, et j'oublie <ostream>, je veux ou bien qu'il y a une erreur
| de compilation, ou bien que ça marche correctement. Je ne veux pas que
| le compilateur choisi un << inattendu parce qu'il n'y a qu'une moitié de
| l'ensemble de surcharge visible.
|
| Ce qui m'intéresse ici, c'est notre vieil ami :
|
| #include <iostream>
|
| int main()
| {
| std::cout << "Hello, world!n" ;
| return 0 ;
| }
|
| Nous somme bien d'accord (je crois) que :
| - ce programme n'est pas portable, au moins selon la norme, et
| - une implémentation a le droit de le faire marcher.

une implémentation a aussi le droit de ne pas le faire marcher.

| La question que je me pose, c'est que si l'implémentation ne le fait pas
| marcher, est-ce qu'un diagnostique est exigé ou non.

La norme ne demande pas à l'implémentation de documenter ce qui se
passe. En particulier, la réponse à ta question est « undefined
behaviour ».

[...]

| Et en lisant la norme soigneusement, sans préjugés sur ce que je sais
| (ou crois savoir) des intentions, je trouve la garantie. Pas que ça
| m'aide réelement, parce que les implémentations et la norme, ce sont
| deux choses distinctes. Et je crois que la garantie, c'est réelement
| accidentale, et non voulue.

Elle est où la garantie ?

| (Mais alors, pourquoi dire que l'en-tête
| peut inclure d'autres en-têtes standard, plutôt que de simplement dire
| qu'il peut définir et/ou déclarer des choses décrites dans d'autres
| en-têtes ? Est-ce que le choix de mots est significatif d'une intention,
| ou non ?)

-- Gaby
1 2