Utilisation de la STL avec Compaq Visual

Utilisation de la STL avec Compaq Visual - C++ - Programmation

Marsh Posté le 01-12-2004 à 11:00:04    

Bonjour, j'essaie de compiler un programme nécessitant l'utilisation de la STL sous Compaq Visual (Version 6.0). Malheureusement, il semble que le " #include <list.h> " soit refusé. A la compilation, avant même l'édition de lien, j'ai, en effet le message d'erreur suivent :
 
d:\program files\microsoft visual studio\vc98\include\list.h(37) : error C2146: syntax error : missing ';' before identifier 'Length'
d:\program files\microsoft visual studio\vc98\include\list.h(37) : error C2501: 'DWORD' : missing storage-class or type specifiers
d:\program files\microsoft visual studio\vc98\include\list.h(37) : error C2501: 'Length' : missing storage-class or type specifiers
d:\program files\microsoft visual studio\vc98\include\list.h(53) : error C2146: syntax error : missing ';' before identifier 'GetPrevLink'
d:\program files\microsoft visual studio\vc98\include\list.h(53) : error C2433: 'WINAPI' : 'inline' not permitted on data declarations
d:\program files\microsoft visual studio\vc98\include\list.h(53) : fatal error C1004: unexpected end of file found
 
....
 
MyProject.exe - 7 error(s), 0 warning(s)
 
Sauriez vous d'où ça vient ? J'ai regardé un peu les précédents messages de ce forum mais je n'ai rien trouvé de similaire. Merci de votre aide !
 
Nathan g
 

Reply

Marsh Posté le 01-12-2004 à 11:00:04   

Reply

Marsh Posté le 01-12-2004 à 11:02:44    

"Compaq Visual"... c'est pas un truc FORTRAN plutot ça ?
"microsoft visual studio\vc98" c'est pas Visual C++ que tu utilises plutot ?
En tous cas si tu veux utiliser std::list c'est <list> sans le h qu'il faut inclure, pas <list.h>.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 01-12-2004 à 11:10:58    

Effectivement, Compq Visula est à la base pour le fortran, mais j'arrive, sans problème normalement, à créer des programmes C ou C++ (notamment quand je dois faire des appels à partir du fortran sur des fonctions qui ont été écrites dans ce langage).
 
 
Sinon, #include <list.h> a toujours marché avant (sous Linux et gcc) pour moi. Je vais tenter l'autre écriture. Mais, en fait, je crois qu'il trouve bien le fichier de déclaration de la stl mais il n'arrive pas à compiler avec !

Reply

Marsh Posté le 01-12-2004 à 11:15:20    

Si c'est comme <string> et <string.h> c'est pas étonnant que ça maÿrde. Ils ont rien à voir.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 01-12-2004 à 11:40:10    

Bon, faut que j'essaie de clarifier qqch. Apparement, avant, sous linux et gcc, j'utilisais, pou faire appel à la stl, #include<list> et #include <list.h>. Les deux donnaient le même résultat et peremttaient la création de liste STL.
 
Maintenant, la nouvelle écriture propre consiste à utiliser des namespaces.
 
Ainsi, effectivement, avec visual fortran, l'écriture  
 
#include<list>
using namespace std;
 
marche et permet de créer des listes.
 
De même, l'écriture ancienne :
 
#include <iostream.h>
 
est à remplacer par:
 
#include <iostream>
using namespace std;
 
L'appel à l'espace de nommage std est dorénavant préférable. Il est vrai que cette nouvelle écriture m'évite des warnings avec des compilateurs récents.
 
J'ai bon ou j'ai écrit une connerie ?
 
Ce qui est "marrant" avec visual, c'est que si l'écriture  
 
#include<list>
using namespace std;
 
marche, celle de :
 
#include <iostream>
using namespace std;
 
n'est pas accepté (il est nécessaire de conserver l'ancienne écriture #include <iostream.h> pour pouvoir faire des cout, endl etc ...)

Reply

Marsh Posté le 01-12-2004 à 13:35:31    

Cette "nouvelle" écriture est la règle depuis la norme qui date de 98. VC++ 6 est antérieur à cette norme et donc il ne respecte pas tout ça. Change de STL ou mieux de compilo (VC++ 2003 tant qu'à faire).
http://c.developpez.com/faq/cpp/?p [...] L_iostream


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 02-12-2004 à 09:18:55    

En fait, après quelque changement dans les options, il semble que ce soit accepté. J'ai du raterqqch à la création du projet mais je ne sais pas quoi.
Par contre, il y a bien un fichier list.h dans les include de Visual, en même temps qu'un list. Je ne suis pas sur, effectivement, que le premier corresponde réellement à la STL. A contrario, il y a juste un fichier vecto et pas de vector.h. La, pas de doute sur l'utilisation de la STL.

Reply

Marsh Posté le 02-12-2004 à 11:51:42    

Ben si c'est le même que chez moi, non, ça n'a rien à voir:
http://doc.ddart.net/msdn/header/include/list.h.html
 
Juste pour info : ton VC++, il a été est livré avec Compaq Visual ou il a été installé à côté ?


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 02-12-2004 à 12:34:52    

Ca je ne saurais pas te le dire. Je l'utilise juste. C'est l'administrateur de la machine qui l'a installé.
En fait, VisualC++ apparaît comme "Additional Information" dans la Fenêtre "About Visual Fortran". Je ne sais pas si ça répond à ta question.
 
 
Juste une autre petite question. Sous Visual, je n'arrive pas à compiler un programme du type :
 
class Article;
 
int main()
{
    list<Article>::iterator it;
 
    ....
}
 
J'ai un message du type :
 
d:\program files\microsoft visual studio\vc98\include\list(29) : error C2079: '_Value' uses undefined class 'Article'
 
Par contre, sous Linux et gcc, ça passe très bien pourtant.
 
Pourquoi, semble t-il qu'il faille sous Visual que Article soit défini (et non pas seulement déclaré).  
 
Encore une bizarrerie de Visual !
 
Dans les deux systèmes, par contre, une ligne du type :
 
list<Article*>::iterator it;
 
est acceptée.

Reply

Marsh Posté le 02-12-2004 à 13:23:16    

Non c'est normal. Tu fais une forward declaration de Article. Je vois pas comment gcc ou un autre pourrait deviner ce qu'il y a dedans et comment ton code peut compiler avec.
Fais un include de "Article.h".
Pour voir le contenu de list.h c'est pas compliqué tu l'ouvres.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 02-12-2004 à 13:23:16   

Reply

Marsh Posté le 02-12-2004 à 13:32:14    

Effectivement, je comprends qu'il puisse y avoir un problème mais une telle écriture est pourtant acceptée par mon compilateur et marche (a partir du moment où le programme est cohérent et que l'utilisation de *it se fait avec une valeur de it donnée précédemment comme égal à un vrai itérateur).
 
en travaillant sous Visual, je vais être obligé de revoir tout mon programme.

Reply

Marsh Posté le 02-12-2004 à 13:46:51    

Autre point marrant (et pourtant nécessaire pour moi) est le fait que l'écriture de :
 
list<list<Article*>::iterator> it;
 
est acceptée par Visual mais avec un nombre impressionnant de warnings à la compilation !

Reply

Marsh Posté le 02-12-2004 à 15:13:05    

VC++ 6 a du mal avec les templates et donc la STL c'est pas nouveau. Il a plus de 6 ans quand même...
Après list<Article>::iterator it;  qui marche avec uen forward declaration de Article je suis sceptique. Le compilo doit instancier std::list avec Article, et il ne sait rien d'Article, donc je ne vois pas comment c'est possible.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 02-12-2004 à 16:26:49    

Sinon, si
 
list<Article>::iterator it;
 
n'est pas accepté à la compilation, y a t-il un moyen de faire accepter un pointeur sur cet iterateur du style :
 
(list<Article>::iterator)* it;
 
Apparemment, ce n'est pas accepté par Visual non plus. Y a t'il un moyen de créer des pointeurs sur des itérateurs de liste d'Objet (et non pas de liste de pointeurs sur ces objets) ?
 
Je pose cette question toujours dans le but de diminuer les modifications que j'aurais à faire dans mon code initial.

Reply

Marsh Posté le 02-12-2004 à 16:30:58    

nathan_g a écrit :

Autre point marrant (et pourtant nécessaire pour moi) est le fait que l'écriture de :
 
list<list<Article*>::iterator> it;
 
est acceptée par Visual mais avec un nombre impressionnant de warnings à la compilation !


Oui, à cause des symboles qui font plus de 256 caractères. Débarasse toi de ce warning avec le pragma qui va bien.
 
Sinon, list<Article>::iterator it; Ca ne marche pas avec VC6.
Il faut le faire en 2 étapes:
  typedef list<Article> MaListe;
  Maliste::iterator it;

Reply

Marsh Posté le 02-12-2004 à 16:55:00    

Etant novice en VC6, j'ose poser la question :
 
Qu'est ce que c'est qu'un " pragma " ?
 
Sinon, j'ai essayé ton écriture, mais j'ai du mal m'y prendre car j'ai toujours des messages d'erreur similaire. Par exemple avec un fichier .cpp, où j'ai des méthodes de la classe Article, j'ai tenté d'écrire :
 
class Boisson;
 
int Valeur::calculcarre()
{
 typedef list<Boisson> Eau;  
 Eau::iterator it;
 
...
}
 
J'ai le message d'erreur
 
d:\program files\microsoft visual studio\vc98\include\list(29) : error C2079: '_Value' uses undefined class 'Boisson'
        E:\...\Valeur.cpp(13) : see reference to class template instantiation 'std::list<class Boisson,class std::allocator<class Boisson> >' being compiled
 
La ligne typedef list<Boisson> Eau; est acceptée mais pas la suivante. En fait ce qui m'intéresserait ce serait que les deux lignes soit acceptée à la compilation dans les arguments protected d'une classe où la définition de boisson ne serait pas encore connue. Est-ce possible ?

Reply

Marsh Posté le 02-12-2004 à 16:58:52    

nathan_g a écrit :

Etant novice en VC6, j'ose poser la question :
 
Qu'est ce que c'est qu'un " pragma " ?
 
En fait ce qui m'intéresserait ce serait que les deux lignes soit acceptée à la compilation dans les arguments protected d'une classe où la définition de boisson ne serait pas encore connue. Est-ce possible ?


Ah ok, t'as 3 problèmes donc.
 
1. Le pragma, quelqu'un d'autre t'expliqueras, mais met juste ça au début de tes fichiers:
#pragma warning(disable:4786)
 
2. Oui, pour mettre des trucs dans tes listes, il faut que les trucs en questions soit définis. Pour faire ce que tu souhaites, il faut passer par des pointeurs et des forward class declarations.  
 
3. Tu dois ceci-dit garder l'écriture que je t'ai donné.  
 
Donc:
 
class Boisson;
typedef std::list<Boisson *> Eau;
Eau::iterator it;
 

Reply

Marsh Posté le 02-12-2004 à 17:05:21    

Ok, je commence à comprendre.
 
Mais, si écrire  
 
class Boisson;  
typedef std::list<Boisson *> Eau;  
Eau::iterator it;  
 
revient exactement à :
 
list<Boisson*>::iterator it;
 
(à part que la list Eau n'est plus définie)
alors autant prendre cette dernière écriture car elle sera acceptée. Le seul intérêt que je cherchais dans ton écriture était de pouvoir écrire qqch d'équivalent à
 
list<Boisson>::iterator it;
 
sans que Boisson soit défini (mais juste déclarer). Ce qui est impossible d'après ce que tu viens de m'écriture.
Je pense donc conserver des écritures du type :
 
list<Boisson*>::iterator it;
 
et revoir tout mon code.

Reply

Marsh Posté le 02-12-2004 à 17:07:44    

Oui, passer par un typedef est équivalent à ta permière écriture, mais celle-ci passe souvent mal avec Visual C++ 6.  
 
C'est un vieux compilo comme te l'a dis HelloWorld. Je pensais jute que tes problèmes avec VS6 étaient dûs à ça.

Reply

Marsh Posté le 02-12-2004 à 17:35:01    

Donc tu vas te gérer une liste de pointeurs de Boisson... T'es sûr que ça va pas créer plus de pblm que ça va en résoudre. Introduire des pointeurs ça veut dire gérer des new et des delete... Tout ç apour quoi ? J'ai pas pigé ce qui t'empêche d'include ta classe.
Une fois que tu as un itérateur, tu en fais quoi vu que la classe pointée n'est pas définie ?


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 02-12-2004 à 18:23:13    

Merci de votre intérêt pour mon problème,
 
En fait, voici le détail. J'ai, dans une classe de base, Magasin une liste d'objet Rayon. Chaque fois qu'un nouveau Rayon est créé, on lui crée, comme arguments de la class, une liste de pointeurs sur des Articles déja créé (en même temps que la classe magasin d'ailleurs). Mon problème est ensuite de donner comme argument des Articles un itérateur sur l'élément de la liste Rayon dont ils sont issus.
 
J'espère avoir été clair.
 
En gros, on a :
---------------------------
class Magasin
{
 
protected:
 
list<Rayon> _list_ray;
};
---------------------------
class Article;
 
class Rayon
{
 
protected
 
list<Article*> _list_part;
};
---------------------------
 
Quand un nouveau rayon est créé, il s'ajoute à la liste _list_ray. On peut alors commencer à ajouter des éléments dans _list_part, avec les adresses des articles (qui sont stockés ailleurs, dans un tableau de taille fixes car on connait initialement leurs nombre total dans le magasin). Le problème est donc dans la définition de la class Article, qui maintenant ne peut plus contenir d'itérateur sur un des éléments de _list_ray.
 
Avant (et ça marchait !), j'avais :
 
class Rayon;
 
class Article
{
 
protected:
 
list<Rayon>::iterator  _it_rayon;
}
 
 
Maintenant, comme la dernière ligne n'est plus acceptée, il faudrait, je pense la remplacer par un pointeur :
 
Rayon* _p_rayon;
 
pour me repérer dans la liste _list_ray (mais repérer par un pointeur des éléments ajouter dans une liste c'est assez tordu). Ou alors, je remplace _list_ray par une liste de pointeur des zones allouées où sont stockées les rayons. J'aurais :
 
class Magasin
{
 
protected:
 
list<Rayon*> _list_ray;
};
 
et :
 
class Rayon;
 
class Article
{
 
protected:
 
list<Rayon*>::iterator  _it_p_rayon;
}
 
mais ça me fera beaucoup plus de modifications !
 
Qu'en pensez-vous ? Ya t'il une solution simple à ce problème de références croisées ?
 
Finalement, j'ai été bien long. J'espère au moins avoir fait, à peu-près, comprendre mon problème.
 
Merci encore du temps que vous avez pris a me répondre !
 

Reply

Marsh Posté le 03-12-2004 à 09:02:13    

Mouais, j'ai peut-être été un peu long dans les explications. Le plus simple est sans doute de dire que le  
 
list<Article>::iterator it;
 
qui n'est pas autorisé si la classe Article n'a pas été défini, mais juste été déclaré, peut être remplacé par :
 
Article* it;
 
qui m'est autorisé et me permettra de faire exactement la même chose (ie. Pourquoi s'amuser à repérer des éléments d'une liste par des itérateurs quand un simple pointeur est plus souple et permet de travailler identiquement sur les éléments de cet liste ?).

Reply

Marsh Posté le 03-12-2004 à 09:08:45    

nathan_g a écrit :

Pourquoi s'amuser à repérer des éléments d'une liste par des itérateurs quand un simple pointeur est plus souple et permet de travailler identiquement sur les éléments de cet liste ?).


 
tu serais pas du genre j'aime me prendre le choux pour rien ...

Reply

Marsh Posté le 03-12-2004 à 09:14:01    

Si tu l'entends dans le sens  
 
Pourquoi utiliser une liste quand un tableau suffit et qu'on lui associe naturellement des pointeurs pour repérer les éléments ? La réponse est non.
 
J'ai besoin, pour mon travail, de construire une liste d'objets, mais, pour les repérer dans cette liste dans une  
autre classe, je ne crois pas avoir d'autre choix que d'utilser des pointeurs et non des itérateurs.

Reply

Marsh Posté le 03-12-2004 à 09:14:52    

et vector<T> c'est pour les lévriers afghans certainement ....

Reply

Marsh Posté le 03-12-2004 à 09:34:00    

Je ne vois pas trop la différence (ou alors on ne se comprend pas). Qu'est ce que je ne peux pas faire avec la list de STL que je pourrais faire avec vector<T> ?

Reply

Marsh Posté le 03-12-2004 à 09:38:26    

vector<T> EST un modéle de TABLEAU générique. list<T> est une liste.
Maintenant va lire ton cours d'algo et tu verras la différence ...

Reply

Marsh Posté le 03-12-2004 à 09:45:04    

Je me répère peut être mais j'ai qqch du genre (en considérant que l'on cherche à repérer des éléments de type Article placés dans une liste) :
 
class Article;
...
list<Article>::iterator _itlist; // => pas autorisé
 
Article* _plist; // => autorisé
 
Que j'ai mes éléments Article placé dans un vector ne changera

Reply

Marsh Posté le 03-12-2004 à 09:48:06    

Je reprends, pardon pour l'envoi trop rapide :
 
Je me répère peut être mais j'ai qqch du genre (en considérant que l'on cherche à repérer des éléments de type Article placés dans une liste) :
 
class Article;
...
list<Article>::iterator _itlist; // => pas autorisé
 
Article* _plist; // => autorisé
 
Que j'ai mes éléments Article placé dans un vector ne changera rien :
 
class Article;
...
vector<Article>::iterator _itlist; // => pas autorisé
 
Article* _plist; // => autorisé
 
Donc, le seul moyen de repérer les éléments Article de la liste est l'utilisation de pointeur et non d'itérateurs. Le placement des objets Article dans un vector n'y changera rien. La création d'un itérateur vers un élément d'un vector<Article> n'est pas autorisé tant que la classe Article n'est pas défini.

Reply

Marsh Posté le 03-12-2004 à 09:48:33    

Ben ecoute, revois la structure d'inclusiond e ton code, exporte des interfaces et ca ira mieux. C'ets pas parceque tu ne SAIS pas ecrire ca correctement que tu dois passer par des trucs abracadabrantesques ...
 
Les chema d'include c'est quand même la base à maitriser.
Y a un excellent article à ce sujet sur www.flipcode.com (si ca vit encore).

Reply

Marsh Posté le 03-12-2004 à 10:15:00    

Désolé, mais je ne comprends pas ce que tu me proposes. J'ai vraimeent l'impression que l'on parle de choses différentes.
Je ne vois pas comment on peut repérer un élément donné dans une liste "list<Article> " autrement que par un pointeur, à partir de l'instant où cette position est un argument d'une autre classe et que dans la déclaration de cette autre classe, Article n'est pas encore déclaré !

Reply

Marsh Posté le 03-12-2004 à 10:17:45    

.... Il faut que tu repense ton schema d'inclusion : cad la maniere dont tes fichiers .h s'imbriquent pour permettre a Article d'etre visible par ta classe.

Reply

Marsh Posté le 03-12-2004 à 10:33:02    

Ah OK !
Eh ben en fait, ça n'est pas possible car les inclusions sont dajé réalisée depuis trop longtemps dans le code. Le problème est celui des références croissées (pour simplifier).
 
J'ai une classe A qui contient une liste d'élements de la classe B. Lorsqu'on rajoute des éléments B à A, ils ont eux-mêmes besoin de savoir dans quel objet de la classe A ils se trouvent :
 
fichier A.H :
 
#include "B.H"
 
class A
{
 
list<B> toto;
}
 
fichier B.H :
 
class A;
 
class B
{
 
list<A>::iterator repere_de_A;
}
 
Problème : la dernière ligne n'est pas acceptée par VC++ (elle l'était sous linux par gcc)
 
Solution envisagée :
 
modification de  
 
list<A>::iterator repere_de_A; // => pas acceptée
 
en
 
A* repere_de_A; // => acceptée
 
ou alors (je le reconnais ce serait bcp plus propre mais trop compliqué à faire dans mon code actuel) :
 
fichier A.H :
 
class B;
 
class A
{
 
list<B*> toto;
}
 
fichier B.H :
 
#include "A.H"
 
class B
{
 
list<A>::iterator repere_de_A; // accepté
}
 
 
Et donc on alloue dynamiquement, à chaque création d'un élément B, de la memoire pour le stocker. On ajoute dans toto un pointeur sur cet espace mémoire et, dans B, on initialise l'itérateur permettant de repérer dans la liste des A la position de celui qui le contient.

Reply

Marsh Posté le 03-12-2004 à 10:34:29    

Bah faut reprendre ca sinon tu va a l'encontre de probleme epineux.
Passez par des A* c'est le meilleur moyen de se flinguer.

Reply

Marsh Posté le 03-12-2004 à 10:43:30    

Au passage si tu pouvais utiliser la balise cpp pour formater ton code :sweat:


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 03-12-2004 à 10:43:57    

Qu'est ce que tu entends par se flinguer ?
 
C'est à dire rencontrer des erreurs à l'éxécution même si la compilation se passe bien ? où avoir un code non portable ?
 
D'ailleurs je ne comprends toujous pas vraiment pourquoi :
 
class Machin;
 
class Truc
{
 
list<Machin>::iterateur it;
}
 
n'est pas autorisé. A l'initialisation, it n'a pas besoin de savoir vers quoi il itère, jusqu'il doit itérer. En un sens, il n'est pas porteur de plus d'informations qu'un pointeur pmachin définit par :
 
Machin* pmachin;
 
qui, lui, pourtant, est permis comme argument de la classe Truc.
 

Reply

Marsh Posté le 03-12-2004 à 10:48:40    

Regardes l'implantation de list<T> tu verras qu'il a besoin de connaitre la taille de l'objet T qu'il va stocker. Pour connaitre la taille, le compilateur doit avoir acces à l'ensemble de la définition des membres.
 
utiliser des A* au lieu d'iterator avec la STL c'est :
* Montrer qu'on a pas tout piger au concept de conteneurs
* s'exposer à des soucis de portabilités
* s'exposer a des memory leaks à retardement.

Reply

Marsh Posté le 03-12-2004 à 10:54:47    

En gros, tu me recommandes plutot la seconde solution (qui respecte la philosophie STL) de :
 
fichier A.H :  
 
class B;  
 
class A  
{  
 
list<B*> toto;  
}  
 
fichier B.H :  
 
#include "A.H"  
 
class B  
{  
 
list<A>::iterator repere_de_A; // accepté  
}  
 
Même si tu as raison sur l'implantation de list<T>, il reste lourd que list<T>::iterator nécessite, lui, de connaître la taille de T (elle n'est pas nécessaire, au moins à la création). Enfin, je crois rester obligé de faire des A*, aussi dangereux que ce soit (question de temps, je suis plus dans une logique de "Faut que ça marche rapidement !" que "Faut que ce soit écrit proprement !" ).

Reply

Marsh Posté le 03-12-2004 à 10:56:12    

OK. L'important soit que tu restes conscient de ce fait pour plus tard.

Reply

Marsh Posté le 03-12-2004 à 10:58:34    

OK, Merci encore du temps passé à me répondre. Je vais tenter, quand même, de rester dans une écriture la plus propre possible.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed