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
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<int>, T >. 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.
-- ;-)
On Tue, 2 Nov 2004 21:41:56 +0100, "Marc" <metrica@free.fr>:
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<int>, T >. 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.
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<int>, T >. 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.
-- ;-)
Marc
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
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
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
Fabien LE LEZ
On Tue, 2 Nov 2004 21:41:56 +0100, "Marc" :
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) {}
On Tue, 2 Nov 2004 21:41:56 +0100, "Marc" <metrica@free.fr>:
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)
{}
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) {}
On Tue, 02 Nov 2004 23:24:00 +0100, Fabien LE LEZ :
int coordonnee= (i>=size_coord) ? 0 :
Oups, la ligne est coupée ici. Il fallait lire
int coordonnee= (i>=size_coord) ? 0 : coord[i];
-- ;-)
Marc
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
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
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
Marc
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
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
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
Fabien LE LEZ
On Thu, 4 Nov 2004 12:18:25 +0100, "Marc" :
ç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<>...
-- ;-)
On Thu, 4 Nov 2004 12:18:25 +0100, "Marc" <metrica@free.fr>:
ç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<>...
Non. Je ne sais plus quel mécanisme est en jeu, mais en pratique, ça marche :-) D'ailleurs, regarde le constructeur de std::vector<>...
-- ;-)
Loïc Joly
Marc wrote:
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.
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
Marc wrote:
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.
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.
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.
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
Marc
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
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
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
Fabien LE LEZ
On Thu, 4 Nov 2004 12:18:25 +0100, "Marc" :
ç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.
-- ;-)
On Thu, 4 Nov 2004 12:18:25 +0100, "Marc" <metrica@free.fr>:
ç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.
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.