OVH Cloud OVH Cloud

Un vecteur dans une structure???

22 réponses
Avatar
Ataya
Voila, tout est dans le titre, je cherche a mettre un vecteur dans une
structure:

Voila mon code:

typedef struct {int xV;
int yV;
vector<tabVoisine>(1); }Ville;



Le message d'erreur:
Impossible de cr=E9er la sp=E9cialisation template depuis
'vector<T,Allocator>'


Je ne comprend pas le message d'erreur, qq'un aurait il une id=E9e,

Merci.

10 réponses

1 2 3
Avatar
Sylvain
Ataya wrote on 25/03/2006 16:55:

struct Ville
{
int xV;
int yV;
std::vector <Ville *> voisines;

};

_Est-ce du c++ de déclarer les struct de cette manière?


en complément du point d'Etienne:

une déclaration de classe (par le mot "class") ou d'une structure (par
le mot "struct") est "grossièrement équivalente" (pour des définitions
simples), une première différence est simplement que tous les membres
d'une structure sont publics (visibles de tous, partout) alors que les
membres d'une classe sont (implicitement) protégés.

_Le fait de faire une de strucuture contenant un tableau de cette meme
strucutre pose il un probleme particulier?


cela vous impose simplement de déclarer la structure (le "struct
Ville;") avant de la définir (le "struct Ville { la_definition };").

Sylvain.

Avatar
Loïc Joly
Ataya wrote on 25/03/2006 16:55:


struct Ville
{
int xV;
int yV;
std::vector <Ville *> voisines;

};

_Est-ce du c++ de déclarer les struct de cette manière?



en complément du point d'Etienne:

une déclaration de classe (par le mot "class") ou d'une structure (par
le mot "struct") est "grossièrement équivalente" (pour des définitions
simples), une première différence


Je n'en connais pas d'autres...

est simplement que tous les membres
d'une structure sont publics


(par défaut, ça peut se changer)

(visibles de tous, partout) alors que les
membres d'une classe sont (implicitement) protégés.


Privé et non pas protégés. Et par défaut uniquement aussi.

--
Loïc


Avatar
Sylvain
Loïc Joly wrote on 26/03/2006 01:40:

les membres d'une classe sont
(implicitement) protégés.


Privé et non pas protégés.


merci de cette précision.

"protégé" se lisait ici (selon le langage courant) non accessible,
masqué, ..., il est plus pertinent de dire "private" en effet (pour
éviter une méprise avec "protected")

Et par défaut uniquement aussi.


ce que dit exactement "implicitement".

Sylvain.


Avatar
kanze.james
Sylvain wrote:
Etienne Rousee wrote on 25/03/2006 13:19:
[*] En l'occurence, duplication de l'information "v1 est
voisine de v2", sous la forme "v2 est voisine de v1".


Ok, mais ce n'est pas bien gênant.


c'est même, imho, la meilleure façon (la plus rapide, la moins
coûteuse) pour permettre de trouver toutes les villes voisines
d'une ville quelconque.

mais Fabien a peut être un meilleur algo.


Une fois n'est pas coutume, mais... Je suis tout à fait d'accord
avec Sylvain. Fabien a certes raison quand il parle d'une
duplication d'information, mais j'aimerais bien savoir les
alternatifs. Il s'agit ici d'établir un rapport
bi-directionnel ; logiquement, on imagine bien une classe
« gestionnaire » des rapports, mais dans la pratique, je n'ai
jamais réelement vu de solution qui marche.

Ce qu'il faut, évidemment, c'est un système de notification,
pour que quand je supprime une ville, toutes les villes voisines
en soient notifiées, pour en supprimer le rapport chez eux.
Dans le cas précis des villes, on pourrait imaginer que le
programme interdit les armes nucléaire, et donc, qu'on ne
supprime jamais de ville. Mais en général, c'est un problème non
trivial qu'il faut toujours aborder. Et comme je dis, si Fabien,
ou qui que ce soit d'autre, en a une bonne solution, j'en suis
preneur.

--
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
kanze.james
Sylvain wrote:
Ataya wrote on 25/03/2006 16:55:

struct Ville
{
int xV;
int yV;
std::vector <Ville *> voisines;

};

_Est-ce du c++ de déclarer les struct de cette manière?


en complément du point d'Etienne:

une déclaration de classe (par le mot "class") ou d'une
structure (par le mot "struct") est "grossièrement
équivalente" (pour des définitions simples), une première
différence est simplement que tous les membres d'une structure
sont publics (visibles de tous, partout) alors que les membres
d'une classe sont (implicitement) protégés.


Le « grossièrement », c'est de trop -- qu'on utilise le mot clé
struct ou le mot clé class, c'est toujours une classe qu'on
définit. On peut même écrire :

struct Ville ;
class Ville { } ;

ou vice-versa.

_Le fait de faire une de strucuture contenant un tableau de
cette meme strucutre pose il un probleme particulier?



Attention : la structure ici ne contient pas de tableau de la
même structure. Elle en contient un tableau de pointeurs à la
même structure. C'est une différence de poids. (Logiquement, il
n'y a pas de raison pourquoi std::vector< Ville > voisines ne
marcherait pas non plus. Mais la norme l'interdit. Et
évidemment, Ville voisines[N] ne pourrait jamais marcher.)

cela vous impose simplement de déclarer la structure (le
"struct Ville;") avant de la définir (le "struct Ville {
la_definition };").


Même pas. Le « struct Ville » en tête de la définition suffit.

--
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
Sylvain
wrote on 26/03/2006 21:04:

Le fait de faire une de strucuture contenant un tableau de
meme cette strucutre pose il un probleme particulier?




[j'ai recopié la question d'origine pour plus de clarté.]

cela vous impose simplement de déclarer la structure (le
"struct Ville;") avant de la définir (le "struct Ville {
la_definition };").


Même pas. Le « struct Ville » en tête de la définition suffit.


La question n'était pas "le fait de déclarer une classe avec le mot clé
struct etc", mais simplement "faire une structure".

Alors:

struct {
int x, y;
Ville* voisines;
} Ville;

est invalide, tandis que:

struct Ville;
struct {
int x, y;
Ville* voisines;
} Ville;

est valide.

(je sais "c'est pas du C++ etc, etc", mais c'est tout de même dans la
question).

Sylvain.



Avatar
Marc Boyer
Le 26-03-2006, Sylvain a écrit :
La question n'était pas "le fait de déclarer une classe avec le mot clé
struct etc", mais simplement "faire une structure".

Alors:

struct {
int x, y;
Ville* voisines;
} Ville;


Sauf que ce code déclare une variable Ville de type anonyme.
Je pense qu'il manque un typedef pour faire ce que vous vouliez
faire.

est invalide, tandis que:

struct Ville;
struct {
int x, y;
Ville* voisines;
} Ville;

est valide.

(je sais "c'est pas du C++ etc, etc", mais c'est tout de même dans la
question).


Je suis un peu perdu dans ce fils pour retrouver 'la question'.
Le fait est que C++ a simplifié l'usage du mot clef struct en
permettant
struct Ville {
int x,y;
Ville* voisines;
};

Après, essayer de retrouver les limitations du C avec un compilo C++
ne me semble pas d'un grand intérêt.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)

Avatar
Jean-Marc Desperrier
wrote:
Ce qu'il faut, évidemment, c'est un système de notification,
pour que quand je supprime une ville, toutes les villes voisines
en soient notifiées, pour en supprimer le rapport chez eux.
Dans le cas précis des villes, on pourrait imaginer que le
programme interdit les armes nucléaire, et donc, qu'on ne
supprime jamais de ville.


Aucun problème s'il travaille pour une assurance, les conséquences de la
désintégration du noyau de l’atome sont toujours exclues :-)

Mais en général, c'est un problème non
trivial qu'il faut toujours aborder. Et comme je dis, si Fabien,
ou qui que ce soit d'autre, en a une bonne solution, j'en suis
preneur.


Ca laisse un peu l'impression qu'on pourrait démontrer que c'est non
résolvable de manière statique.

J'ai l'impression que cela peut cependant donner lieu à un bon exemple
d'utilisation des boost::weak_ptr.

La liste globales des villes serait gérée par des boost::shared_ptr, les
relations de voisinages par des boost::weak_ptr, une suppression
impromptue se régle simplement en n'oubliant pas de tester l'échec de
lock() sur les weak_ptr.

D'ailleurs en fait, c'est un peu ce qui me manque par rapport à boost,
des examples concrets et parlant de comment utiliser toutes les classes
fournies dans la vraie vie, weak_ptr étant un example parfait du cas où
la première réaction est "à quoi ça sert vraiment ce truc ?".

Avatar
kanze
Jean-Marc Desperrier wrote:
wrote:

Ce qu'il faut, évidemment, c'est un système de notification,
pour que quand je supprime une ville, toutes les villes
voisines en soient notifiées, pour en supprimer le rapport
chez eux. Dans le cas précis des villes, on pourrait
imaginer que le programme interdit les armes nucléaire, et
donc, qu'on ne supprime jamais de ville.


Aucun problème s'il travaille pour une assurance, les
conséquences de la désintégration du noyau de l?atome sont
toujours exclues :-)

Mais en général, c'est un problème non trivial qu'il faut
toujours aborder. Et comme je dis, si Fabien, ou qui que ce
soit d'autre, en a une bonne solution, j'en suis preneur.


Ca laisse un peu l'impression qu'on pourrait démontrer que
c'est non résolvable de manière statique.


Pourquoi ? A priori, je crois qu'il doit y avoir une solution.

J'ai l'impression que cela peut cependant donner lieu à un bon
exemple d'utilisation des boost::weak_ptr.


Pas du tout. Il faut plus que simplement mettre à null un
pointeur.

La liste globales des villes serait gérée par des
boost::shared_ptr, les relations de voisinages par des
boost::weak_ptr, une suppression impromptue se régle
simplement en n'oubliant pas de tester l'échec de lock() sur
les weak_ptr.


Ce qui pose deux problèmes : d'abord, on a introduit une
collection globale qui n'y était pas avant, qu'il faut gerer, et
deuxièmement, on a une jolie fuite de mémoire, au moins qu'on
puisse garantir venir régarder les villes qui n'y sont plus dans
chacun des voisin d'avant.

Je n'ai pas attendu Boost pour avoir quelque chose d'équivalent,
mais je m'en suis servi en fait assez peu, parce que simplement
mettre à null un pointeur, c'est rare que ça suffisait.

D'ailleurs en fait, c'est un peu ce qui me manque par rapport
à boost, des examples concrets et parlant de comment utiliser
toutes les classes fournies dans la vraie vie, weak_ptr étant
un example parfait du cas où la première réaction est "à quoi
ça sert vraiment ce truc ?".


Dans le cas de weak_ptr, il faut dire : pas grand chose. Il est
utile dans les cas où il faut casser des boucles, et parfois,
dans le cas des call-backs, où on est assuré que l'évenemment
arrivera tôt ou tard (pour que le call-back même soit effacé),
mais il ne remplace pas des notifications dans le cas général.

--
James Kanze GABI Software
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
Jean-Marc Desperrier
kanze wrote:
Jean-Marc Desperrier wrote:
J'ai l'impression que cela peut cependant donner lieu à un bon
exemple d'utilisation des boost::weak_ptr.


Pas du tout. Il faut plus que simplement mettre à null un
pointeur.


J'ai l'impression que l'outils peut être utile, même si ce n'est
assurément pas la solution complète.

La liste globales des villes serait gérée par des
boost::shared_ptr, les relations de voisinages par des
boost::weak_ptr, une suppression impromptue se régle
simplement en n'oubliant pas de tester l'échec de lock() sur
les weak_ptr.


Ce qui pose deux problèmes : d'abord, on a introduit une
collection globale qui n'y était pas avant, qu'il faut gerer, et
deuxièmement, on a une jolie fuite de mémoire, au moins qu'on
puisse garantir venir régarder les villes qui n'y sont plus dans
chacun des voisin d'avant.


Je me demande si on ne se comprend pas mal.
J'avais en tête de partir de ce qu'a proposé Etienne :

struct Ville
{
int xV;
int yV;
std::vector <Ville *> voisines;
// Cette structure ne fera que
// des affectation de pointeurs
};

struct Application
{
std::vector <Ville *> Villes;
// C'est cette structure qui fera les "new"
};

qui se transforme en :

class Ville
{
private:
std::vector< boost::weak_ptr<Ville> > voisines;
public:
int xV;
int yV;
std::vector< boost::shared_ptr<Ville> > getVoisines();
// getVoisines "lock" les voisines dans le vecteur retouné
// Au passage, elle nettoye la liste, et en retire les
// éléments expiré
};

struct Application
{
std::vector< boost::shared_ptr<Ville> > Villes;
};

Je n'ai pas attendu Boost pour avoir quelque chose d'équivalent,
mais je m'en suis servi en fait assez peu, parce que simplement
mettre à null un pointeur, c'est rare que ça suffisait.


Tout seul, certainement, mais il me semble qu'on peut l'utiliser comme
brique de base pour construire dessus ce qui marceh.


1 2 3