 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Marc Guest
|
Posted: Tue Nov 02, 2004 8:41 pm Post subject: pb de tableaux multidimensionnels |
|
|
Y-a-t-il un modèle dans la STL implémentant les tableaux multidimensionnels,
l'équivalent de vector<> pour les tableaux unidimensionnels ?
Nota : je cherche un modèle pour les tableaux de taille quelconque et
variable et pas seulement bi-dimensionnels, ce qui serait facile à
programmer...Par exemple un modèle où dans le constructeur on passerait un
vector<int> spécifiant les dimensions du tableau. J'ai essayé de m'y mettre
et ça coule pas de source...
Marc
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Tue Nov 02, 2004 9:38 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
On Tue, 2 Nov 2004 21:41:56 +0100, "Marc" <metrica (AT) free (DOT) fr>:
| Quote: | Par exemple un modèle où dans le constructeur on passerait un
vector<int> spécifiant les dimensions du tableau.
|
Ça n'existe pas dans la STL, du moins pas directement. Par contre, il
est possible que ce soit dans boost.
Sinon, il est possible d'implémenter ça à partir d'un
std::map < std::vector. Facile à implémenter et très souple,
mais si le tableau est un peu gros et un peu rempli, tu risques de
rencontrer des problèmes de performance.
--
;-)
|
|
| Back to top |
|
 |
Marc Guest
|
Posted: Tue Nov 02, 2004 10:07 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
Merci beaucoup, c'est exactement ce que je cherchais...
J'utilise rarement les map et du coup j'étais parti dans des
vector<vector<..etc..>> , l'horreur sans solution ! alors qu'il y avait si
simple...
Merci encore.
Marc
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Tue Nov 02, 2004 10:24 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
On Tue, 2 Nov 2004 21:41:56 +0100, "Marc" <metrica (AT) free (DOT) fr>:
| Quote: | J'ai essayé de m'y mettre
et ça coule pas de source...
|
En fait, ça me paraît tout de même assez simple, du moins dans le cas
où la taille du tableau est constante.
On commence par quelques types et "helpers" :
typedef std::vector<int> Coordonnees;
typedef Coordonnees Tailles;
int Produit (Tailles const& tableau); // Renvoie le produit des
éléments de "tableau"
int CalculeOffset (Tailles const& tailles,
Coordonnees const& coord)
{
int offset= 0;
int dimension= tailles.size();
int size_coord= coord.size();
for (int i=0; i<dimension; ++i)
{
offset*= tailles[i];
int coordonnee= (i>=size_coord) ? 0 :
// Vérification optionnelle
if (coordonnee > tailles[i])
throw UneExceptionQuelconque();
offset+= coordonnee;
}
return offset;
}
Première version : on ne s'occupe que des éléments, pas des
sous-tableaux :
template <class T>
class TableauMultiDimensionnel
{
public:
TableauMultiDimensionnel (Tailles const& tailles_, T const& t= T())
: tailles (tailles_)
, data (Produit (tailles_), t)
{}
T& operator () (Coordonnees const& coord)
{
if (tailles.size() != coord.size())
throw UneAutreExceptionQuelconque();
return *&data [CalculeOffset (tailles, coord)];
}
T const& operator () (Coordonnees const& coord) const
{ /* même chose */ }
private:
Tailles tailles;
std::vector<T> data;
};
Et les itérateurs me direz-vous ? En première approximation, ceux de
vector<T> ne devraient pas être trop mal :
template <class T>
class TableauMultiDimensionnel
{
....
typedef std::vector<T>::iterator iterator;
iterator begin() { return data.begin(); }
iterator end() { return data.end(); }
... et la même chose en const
....
};
Deuxième version : on peut créer, en prime, des "sous-tableaux" -- par
exemple, une droite ou un plan dans un espace à trois dimensions.
template <class T> class SousTableau
{
public:
SousTableau (Tailles const& tailles, T* data);
// Implémentation évidente
private:
Tailles tailles;
T* data_externe;
};
class TableauMultiDimensionnel
{
public:
SousTableau GetSousTableau (Coordonnees const& coord)
{
return SousTableau (
Tailles (tailles.begin() + coord.size(), tailles.end(),
&data [CalculeOffset (tailles, coord)];
}
....
};
--
;-)
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Tue Nov 02, 2004 11:28 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
On Tue, 02 Nov 2004 23:24:00 +0100, Fabien LE LEZ
<gramster (AT) gramster (DOT) com>:
| Quote: | int coordonnee= (i>=size_coord) ? 0 :
|
Oups, la ligne est coupée ici. Il fallait lire
int coordonnee= (i>=size_coord) ? 0 : coord[i];
--
;-)
|
|
| Back to top |
|
 |
Marc Guest
|
Posted: Wed Nov 03, 2004 9:51 am Post subject: Re: pb de tableaux multidimensionnels |
|
|
Merci beaucoup pour tes explications détaillées.
Effectivement, je suis arrivé à la même solution que toi quand j'ai voulu
initialiser tous les éléments du tableau. Il m'a fallu déterminer une
"stratégie" de parcours du tableau, et donc en quelque sorte déplier le
tableau. Un simple vector convient alors parfaitement...
Marc
|
|
| Back to top |
|
 |
Marc Guest
|
Posted: Thu Nov 04, 2004 11:18 am Post subject: Re: pb de tableaux multidimensionnels |
|
|
J'ai une question subsidiaire à te poser.
Dans ton constructeur, tu écris
TableauMultiDimensionnel (Tailles const& tailles_, T const& t= T())
et donc tu passes la valeur par défaut par référence, transmise par le
temporaire T()
ça ne pose pas de problème dans ce cas ?
où faut-il mieux écrire
TableauMultiDimensionnel (Tailles const& tailles_, T const t= T())
ce qui crée une copie?
J'avoue que je ne comprends pas toujours où est créé puis détruit l'objet
transmis par référence quand on appelle directement un constructeur dans un
appel de fonction...
Marc
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Thu Nov 04, 2004 2:38 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
On Thu, 4 Nov 2004 12:18:25 +0100, "Marc" <metrica (AT) free (DOT) fr>:
| Quote: | ça ne pose pas de problème dans ce cas ?
|
Non. Je ne sais plus quel mécanisme est en jeu, mais en pratique, ça
marche
D'ailleurs, regarde le constructeur de std::vector<>...
--
;-)
|
|
| Back to top |
|
 |
Loïc Joly Guest
|
Posted: Thu Nov 04, 2004 11:33 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
Marc wrote:
| Quote: | J'ai une question subsidiaire à te poser.
Dans ton constructeur, tu écris
TableauMultiDimensionnel (Tailles const& tailles_, T const& t= T())
et donc tu passes la valeur par défaut par référence, transmise par le
temporaire T()
ça ne pose pas de problème dans ce cas ?
|
Petit détail, c'est un passage par référence constante. Autrement, ça ne
serait pas autorisé.
Autrement, la durée de vie de ce temporaire est jusqu'à la fin de
l'évaluation de l'expression, et donc il est valide pendant tout le
temps d'exécution de la fonction.
C'est comme si tu as :
f (int const &i);
f(2+2);
Un entier valant 4 est crée lors de l'évaluation des arguments de la
fonction, et reste valide lors de l'exécution de celle ci, pour être
détruit à la fin de l'évaluation de l'expression contenant un appel de
fonction. Stroustrup discute de designs alternatifs dans le D&E.
| Quote: | où faut-il mieux écrire
TableauMultiDimensionnel (Tailles const& tailles_, T const t= T())
ce qui crée une copie?
|
Dans ce cas, on crée une copie, ce qui n'est pas forcément utile.
--
Loïc
|
|
| Back to top |
|
 |
Marc Guest
|
Posted: Fri Nov 05, 2004 8:22 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
Merci de tes explications.
J'ai appris une chose importante que j'ignorai et pas évidente a priori...
Je suis allé lire le stroustrup et j'ai lu exactement ce que tu m'expliques
sur les références vers objet constant.
Marc
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Fri Nov 05, 2004 8:38 pm Post subject: Re: pb de tableaux multidimensionnels |
|
|
On Thu, 4 Nov 2004 12:18:25 +0100, "Marc" <metrica (AT) free (DOT) fr>:
| Quote: | ça ne pose pas de problème dans ce cas ?
|
En fait, la méthode canonique pour passer un objet (i.e. autre chose
qu'un type de base) en argument d'une fonction est le passage par
référence constante. Donc il faut que ça marche, même dans le cas où
il y a une valeur par défaut.
--
;-)
|
|
| Back to top |
|
 |
Marc Guest
|
Posted: Sat Nov 06, 2004 10:19 am Post subject: Re: pb de tableaux multidimensionnels |
|
|
| Quote: | En fait, la méthode canonique pour passer un objet (i.e. autre chose
qu'un type de base) en argument d'une fonction est le passage par
référence constante. Donc il faut que ça marche, même dans le cas où
il y a une valeur par défaut.
|
Je suis d'accord avec toi, mais on aurait pu penser qu'il faille (aïe)
écrire
void f(const T&);
T x;
f(x);
au lieu de f(T()) directement.
J'ai lu dans le stroustrup que dans ce dernier cas un temporaire est créé
qui a la même "durée de vie" que la portée de la référence qui le pointe (on
se comprend), donc tout le corps de la fonction dans le cas présent.
On peut même écrire
const int &x=1;
x est alors une réfence vers un temporaire non nommé qui contient 1 est est
détruit quand on quitte la portée de x.
Marc
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|