IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

[contribution] tableau 2 dimensions qui utilise la STL


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut [contribution] tableau 2 dimensions qui utilise la STL
    Bonjour à tous,

    je viens d'implémenter une petite classe template qui n'est rien de plus qu'un tableau à 2 dimensions, et qui utilise les std::vector.

    Avant de poster mon code dans la partie "contribution", j'aurais aimé avoir vos critiques et propositions pour l'améliorer.

    Je sais qu'il existe un template qui fait à peu prés la même chose dans boost, mais il n'est pas toujours évident d'installer boost, et la classe que je propose ici est à but didactique (utilisation de vector, templates, etc.)

    Premièrement, une petite classe de test. Mon tableau va être rempli par des instances de cette classe:

    TestClass.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #ifndef DYN_TEST_CLASS
    #define DYN_TEST_CLASS
     
    #include <string>
     
    class TestClass
    {
    public:
    	TestClass(int val = 0, std::string st = "vide");
    	~TestClass(void);
     
    	friend std::ostream& operator << (std::ostream &os, TestClass &source);
     
    	int value;
    	std::string str;
    };
     
    #endif
    TestClass.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include "TestClass.h"
     
    TestClass::TestClass(int val/* = 0*/, std::string st/* = "vide"*/)
    : value(val), str(st)
    {
    }
     
    TestClass::~TestClass()
    {
    }
     
    std::ostream& operator << (std::ostream &os, TestClass &source)
    {
    	os << source.str;
    	return os;
    }
    Ensuite, le tableau en lui-même:
    Dyn2DMatrix.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    // Template class Dyn2DMatrix
    //
    // * la construction de cette matrice se fait de manière à ce que chaque rangée (row) comporte
    //	le même nombre de colonnes (col).
    // * le type contenu dans le tableau doit avoir:
    //		-> un constructeur par défaut,
    //		-> un constructeur de recopie,
    //		-> un opérateur d'affectation.
    // * il est possible de définir un élément neutre (neutralElement) dans le constructeur, cet
    //	élément sert à remplir les trous du tableau. S'il n'est pas défini, l'élément neutre est
    //	construit à partir du constructeur par défaut du type contenu dans le tableau.
    // * lorsqu'un élément est rajouté, la matrice s'aggrandit automatiquement ( voir mutateur )
     
    #ifndef DYN_2D_MATRIX
    #define DYN_2D_MATRIX
     
    #include <vector>
     
    namespace DynMatrix
    {
     
    template <typename T>
    class Dyn2DMatrix
    {
    private:
    	size_t m_nbRow, m_nbCol;
    	std::vector<T> m_array;
    	T m_neutralElement;
     
    public:
    	// --- construction/destruction
    	Dyn2DMatrix()
    		: m_nbRow(0), m_nbCol(0), m_neutralElement(T())
    	{		
    	}
     
    	Dyn2DMatrix(const size_t nbRow, const size_t nbCol)
    		: m_nbRow(nbRow), m_nbCol(nbCol), m_neutralElement(T())
    	{
    		std::vector<T>::iterator it = m_array.begin();
    		m_array.insert(it, nbRow*nbCol, m_neutralElement);
    	}
     
    	Dyn2DMatrix(const T &neutralElement)
    		: m_nbRow(0), m_nbCol(0), m_neutralElement(T())
    	{		
    	}
     
    	Dyn2DMatrix(const size_t nbRow, const size_t nbCol, const T &neutralElement)
    		: m_nbRow(nbRow), m_nbCol(nbCol), m_neutralElement(neutralElement)
    	{
    		std::vector<T>::iterator it = m_array.begin();
    		m_array.insert(it, nbRow*nbCol, m_neutralElement);
    	}
     
    	virtual ~Dyn2DMatrix(){}
     
    	// --- accesseurs
    	T operator() (const size_t row, const size_t col) const
    	{
    		if ( ( m_nbRow < row ) || ( m_nbCol < col ) )
    			throw new std::exception("const Dyn2DMatrix subscript out of bounds");
     
    		return m_array[m_nbCol*row+col];
    	}
     
    	size_t width()	{return m_nbCol;}
    	size_t height()	{return m_nbRow;}
     
    	// --- mutateurs
    	T &operator() (const size_t row, const size_t col)
    	{
    		// Dans un premier temps, je vérifie si la matrice est assez grande.
    		// Si elle ne l'est pas, je l'aggrandis.
     
    		if ( m_nbCol <= col )
    		{// je dois ajouter des colonnes
    			size_t colDiff = col - m_nbCol + 1;
    			for (size_t curRow = 0 ; curRow < m_nbRow ; ++curRow )
    			{
    				std::vector<T>::iterator it = m_array.begin();
    				size_t tmp = curRow*(col+1) + m_nbCol;
    				m_array.insert( it + tmp, colDiff, m_neutralElement);
    			}
    			m_nbCol = col+1;
    		}
     
    		if ( m_nbRow <= row )
    		{// je dois ajouter des rangées
    			std::vector<T>::iterator it = m_array.begin();
    			m_array.insert(it+m_nbCol*m_nbRow, (row - m_nbRow + 1)*m_nbCol, m_neutralElement);
    			m_nbRow = row+1;
    		}
     
    		// puis je retourne simplement l'élément demandé.
    		return m_array[m_nbCol*row+col];
    	}
     
    	// méthode clear: initialise tous les éléments de la matrice avec l'élément passé
    	// en paramètre.
    	void clear(const T &initElement = m_neutralElement)
    	{
    		std::vector<T>::iterator it;
    		for ( it = m_array.begin() ; it != m_array.end() ; ++it)
    			(*it) = initElement;
    	}	
    };
     
    } //namespace
    #endif
    Et finalement, quelque ligne pour tester tout ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // d'abord, une fonction pour afficher la matrice
    template <typename T>
    void displayMatrix(DynMatrix::Dyn2DMatrix<T> matrix)
    {
    	for (size_t i=0; i<matrix.height(); i++)
    	{
    		for (size_t j=0; j< matrix.width(); j++)
    		{
    			cout << matrix(i, j) << "  ";
    		}
    		cout << endl;
    	}
    	cout << endl;
    	getchar();
    }
     
    // et puis un exemple d'utilisation:
    DynMatrix::Dyn2DMatrix<TestClass> matrix(4, 3);
    matrix(2,1) = *new TestClass(4, "toto");
    displayMatrix(matrix);
     
    matrix.clear(*new TestClass(0, "aaaa"));
    displayMatrix(matrix);
     
    matrix(4,3) = *new TestClass(4, "titi");	
    displayMatrix(matrix);
    Voilàvoilà, toute critique est la bienvenue.

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    TestClass serait ici avantageusement remplacé par un tuple. De plus TestClass fait des copies inutiles.
    Tu devrais surcharger l'opérateur() au lieu d'avoir setAt/getAt.
    Il ne faut jamais faire de using namespace au niveau d'un fichier dans un fichier d'entête.
    La fonction display n'a rien à faire là. Tu peux surcharger l'opérateur<< si tu veux, mais faire une fonction display c'est pas terrible.

    Pour une raison obscure, Dyn2Dvector a besoin d'être initialisé avec un pointeur vers un élément, ce qui est absolument non intuitif et inutile, d'autant plus si on veut vraiment l'implémenter, ça peut être fait de meilleure manière.
    On note d'ailleurs qu'il y a un new dans la classe mais pas de delete.

    L'implémentation pourrait aussi être faite avec un simple vector plutôt qu'avec un vector de vectors.
    Il s'agit néanmoins d'une matrice creuse. Ajouter des éléments dont on ne se sert pas ne me semble pas vraiment être une bonne idée.

  3. #3
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    J'ajouterais à tout ça qu'il serait pas mal de fournir des itérateurs. Au moins pour parcourir toute la matrice ; après avoir des itérateurs de colonnes et de lignes ce serait chouette.

  4. #4
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Merci pour vos remarques

    Citation Envoyé par loufoque
    TestClass serait ici avantageusement remplacé par un tuple.
    Qu'est-ce qu'un tuple?

    La fonction display n'a rien à faire là. Tu peux surcharger l'opérateur<< si tu veux, mais faire une fonction display c'est pas terrible.
    Pourquoi? Que proposes-tu?

    Citation Envoyé par loufoque
    Pour une raison obscure, Dyn2Dvector a besoin d'être initialisé avec un pointeur vers un élément, ce qui est absolument non intuitif et inutile, d'autant plus si on veut vraiment l'implémenter, ça peut être fait de meilleure manière.
    Alors oui, alors ça, je ne sais pas comment faire. Car si on passe un objet directement (sans pointeur), je ne sais pas comment faire pour mettre des paramètres par défaut. Comment ferais-tu?

    L'implémentation pourrait aussi être faite avec un simple vector plutôt qu'avec un vector de vectors.
    Ha. Comment?

    Il s'agit néanmoins d'une matrice creuse. Ajouter des éléments dont on ne se sert pas ne me semble pas vraiment être une bonne idée.
    Sur ce point, et les autres que je n'ai pas cité, je dirais que j'aimerais faire simple. Mais toute proposition d'amélioration est la bienvenue

    Citation Envoyé par Laurent Gomila
    J'ajouterais à tout ça qu'il serait pas mal de fournir des itérateurs. Au moins pour parcourir toute la matrice ; après avoir des itérateurs de colonnes et de lignes ce serait chouette.
    En effet, j'y ai pensé. Cependant, j'hésite à rajouter des méthodes, je ne veux pas faire une classe trop grosse. Le but n'est pas d'avoir un truc complet. Juste que ce soit bien codé. Je sais pas...

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Qu'est-ce qu'un tuple?
    Une paire généralisée à n éléments.

    Alors oui, alors ça, je ne sais pas comment faire. Car si on passe un objet directement (sans pointeur), je ne sais pas comment faire pour mettre des paramètres par défaut. Comment ferais-tu?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template<typename T>
    struct Thing
    {
        const T neutral;
     
        Thing()
        {
        }
     
        Thing(const T& t) : neutral(t)
        {
        }
    };
    Note néanmoins que map, qui fait ce genre de choses, utilise uniquement le constructeur par défaut pour définir un neutre.

    Ha. Comment?
    a[x][y] <=> a[y+x*taille], taille étant la taille de la seconde dimension.

    Sur ce point, et les autres que je n'ai pas cité, je dirais que j'aimerais faire simple. Mais toute proposition d'amélioration est la bienvenue
    Tu pourrais par exemple faire une map avec comme clé une paire d'entiers.

  6. #6
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Réponses et commentaires en vrac au fil de la lecture.

    Les classes matricielles peuvent alimenter une série de TD de niveaux débutants à expert.

    * Classe de test:
    - l'opérateur d'affectation a une signature non canonique
    - l'opérateur d'injection devrait prendre une référence constante
    - la chaine est prise par copie
    - l'amitié ne se justifie pas ici
    - les opérations de recopie sont inutiles vu que celles générées par défaut fonctionneront parfaitement bien
    - le construteur de recopie aurait dû utiliser la liste d'initialisation

    * La matrice:
    - l'accesseur (!= mutateur) devrait être déclaré const
    - pourquoi convertir size() en int ? (à la C qui plus est). Autant utiliser le size_type de ton vecteur
    - plutôt que le push_back(newRow), je ferai un resize(size()+1) pour travailler directement sur la nouvelle ligne. Ou alors, juste un swap entre la nouvelle ligne (obtenue par resize) et ton temporaire nommé (newRow) -- Ceci dit, la solution d'un seul vecteur évoquée par loufoque est mieux.


    * Les tuples ne vont guère lui être utiles/pratiques s'il cherche à éviter boost.

    * Je ne suis pas un fervent partisant des itérateurs sur les matrices. Je pêche un peu à en voir l'intérêt et surtout la sémantique. Surtout en l'absence de proxy vecteur (ligne ou colonne).
    D'ailleurs il manque cette classe proxy (qui profiterait sans aucun doute d'un itérateur sur ses éléments)

    Au sujet d'itérateurs, GIL a sorti plein de choses à ce sujet (-> http://opensource.adobe.com)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #7
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Wouch... bon ben j'ai encore du boulot
    En tout cas, merci pour ces remarques

    Il y a tout de même quelques points sur lesquels je voulais revenir:
    -> Quelle est l'utilité d'un proxy pour cette classe?
    -> Les opérateurs de recopie (pour la classe de test) ne sont certes pas indispensables, mais je pensais qu'il serait tout de même bon - toujours dans un but didactique - de les mettre. Je ne sais pas, je ne suis pas enseignant Qu'en pensent les pédagogues?

    Pour le reste, je suis d'accord. En attendant vos réponses, je vais faire les modifications qui s'imposent.

    Encore pour votre participation

  8. #8
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Voilà, j'ai effectué pas mal de modifications d'aprés vos remarques.
    Il reste cependant 2 choses à faire (qui, semble-t-il, sont complémentaires), mais ça dépasse mes compétences:
    * Faire un proxy avec un operateur =
    * Implémenter les itérateurs
    Je ne sais pas comment faire ça, donc si quelqu'un a une idée, au moins une ébauche pour que je puisse me lancer, je suis preneur.

  9. #9
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par r0d
    (a-) Wouch... bon ben j'ai encore du boulot


    Il y a tout de même quelques points sur lesquels je voulais revenir:
    (b-) -> Quelle est l'utilité d'un proxy pour cette classe?
    (c-) -> Les opérateurs de recopie (pour la classe de test) ne sont certes pas indispensables, mais je pensais qu'il serait tout de même bon - toujours dans un but didactique - de les mettre. Je ne sais pas, je ne suis pas enseignant Qu'en pensent les pédagogues?

    (d-)Encore pour votre participation
    a- Comme je le disais, c'est un sujet sur lequel il y a toujours à dire et à faire. Je trouve que c'est vraiment un de ceux qui se prête le mieux à des exercices depuis le niveau débutant jusqu'à celui de concepteur de bibliothèques.

    b- Fournir l'écriture "M[l][c]", pouvoir extraire des vues vecteur de sous zones de la matrice, et donc aller dans la direction d'une meilleure expressivité orientée mathématiques.

    c- Aujourd'hui (*) je préfère montrer les codes réels plutôt que des codes imaginaires qui font des choses inutiles, qui en permettent des dangeureuses, ... Le C++ nous permet de montrer des codes réels qui ne sont pas si compliqués. Et puis cela évite de donner des mauvaises habitudes -- dans le cas présent: l'habitude de perdre du temps sur des choses inutiles et de complèxifier inutilement le code.

    (*) Je ne devais pas penser la même chose il y a quelques années, et mon opinion peut encore évoluer.

    d- Avec plaisir.

    (e-) Voilà, j'ai effectué pas mal de modifications d'aprés vos remarques.
    Il reste cependant 2 choses à faire (qui, semble-t-il, sont complémentaires), mais ça dépasse mes compétences:
    * Faire un proxy avec un operateur =
    * Implémenter les itérateurs
    Je ne sais pas comment faire ça, donc si quelqu'un a une idée, au moins une ébauche pour que je puisse me lancer, je suis preneur.
    e- Il y a peu, j'avais pondu cette prose sur un lieu pas vraiment spécialisé dans le C++. Si tu as besoin d'infos plus précises, demande.

    Comme je l'ai dit, je ne vois pas l'intérêt d'un itérateur sur les élements d'une matrice. Quel sens donner à ++ ? Ou alors partir sur un type d'itérateur super particulier comme ceux conceptualisés dans GIL pour réaliser des for_each. Le proxy vue vecteur est plus pertinent dans un premier temps. Personnellement, quand je manipule des matrices, ce qui m'intéresse, c'est d'abord l'algèbre l'inéaire.

    (f-) [... message que je ne retrouve pas...]
    f- Il me semblait avoir lu que tu voulais pouvoir insérer des lignes et des colonnes.
    Juste un détail. Il faut voir ce que tu vas vraiment faire avec tes matrices. Personnellement, les rares fois où j'ai considéré les matrices comme des entités, il s'agissait de matrices de poids qui devaient pouvoir évoluer dans la phase d'apprentissage de réseaux de neurones artificiels. (En expoitation elles n'étaient considérées plus que comme des valeurs). Il y a effectivement quelques rares cas, ou plus exactement quelques rares agorithmes d'apprentissage, qui demandent à redimensionner des matrices de poids. Le reste du temps, seule la valeur nous importe.

    Tout ça pour dire que. Il faut voir quelles sont les opérations dont tu as véritablement besoin. Proposer des fonctions de redimensionnement, ou d'insertions de colonnes juste parce que l'on pourrait en avoir besoin n'est pas nécessairement la meilleure approche. C'est un peu comme si la SL ne proposait qu'un seul container au lieu du triplet {vecteur, liste, dequeu} parce que au fond ce que l'on veut c'est contenir et pas savoir comment.

    Ce qu'il faut, c'est fournir la version de la matrice la plus adaptée à ton besoin réel.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Luc Hermitte
    a- Comme je le disais, c'est un sujet sur lequel il y a
    toujours à dire et à faire. Je trouve que c'est vraiment un de ceux qui se
    prête le mieux à des exercices depuis le niveau débutant jusqu'à celui de
    concepteur de bibliothèques.
    Un des intérêts majeurs de ce genre d'exercices est d'évaluer et de
    discutter les alternatives
    .

    c- Aujourd'hui (*) je préfère montrer les codes réels plutôt que des
    codes imaginaires qui font des choses inutiles, qui en permettent des
    dangeureuses, ...
    Un autre problème de codes artificiels c'est que généralement ils n'ont pas
    été conçus avec pour objectif une application mais de montrer des
    techniques. Et on se retrouve avec quelquechose dont le seul intérêt est
    de rassembler toutes les techniques désirées et qui va être pris aussi
    comme exemple de conception.

    Comme je l'ai dit, je ne vois pas l'intérêt d'un itérateur sur les
    élements d'une matrice. Quel sens donner à ++ ? Ou alors partir sur un type
    d'itérateur super particulier comme ceux conceptualisés dans GIL pour
    réaliser des for_each. Le proxy vue vecteur est plus pertinent dans un
    premier temps. Personnellement, quand je manipule des matrices, ce qui
    m'intéresse, c'est d'abord l'algèbre l'inéaire.
    Itérateurs sur les lignes et sur les colonnes naturellement. On retrouve
    les vues vecteur.

    Ce qu'il faut, c'est fournir la version de la matrice la plus
    adaptée à ton besoin réel.
    J'ai parlé plus haut de l'effet nocif des exemples destinés à montrer une
    technique qui sont aussi pris comme exemple de conception. Il y a une
    autre source d'exemples qui ne dont pas toujours à suivre: ce sont les
    bibliothèques. Il y a une réelle différence entre concevoir une classe
    pour une bibliothèque et concevoir une classe pour une application. Même
    une classe "générique" comme une classe de matrice. La classe de
    bibliothèque va chercher à l'universalité pour être utilisable dans une
    large classe d'applications. Elle va donc avoir une interface relativement
    grande. La classe de l'application va chercher à avoir l'interface
    minimale nécessaire pour l'application. Pour éviter de mettre des
    contraintes sur l'implémentation et donc en avoir une optimisée.

  11. #11
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Ok. Encore merci

    J'ai donc supprimé, sur vos conseils, le constructeur de recopie et l'opérateur d'affectation.

    Citation Envoyé par Jean-Marc.Bourguet
    Itérateurs sur les lignes et sur les colonnes naturellement. On retrouve les vues vecteur.
    C'est ce que je voulais dire dans mon précédent message. Ce qui serait bien, ce serait un itérateur sur les colonnes, et un itérateur sur les lignes.
    Cependant, je ne sais pas comment m'y prendre. Faut-il implémenter 2 proxies? Un pour chaque?


  12. #12
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par r0d
    le constructeur de recopie
    Ce "re-" m'énerve... Si le mot "recopie" existe en français comme substantif et non forme conjuguée du verbe (il n'est pas dans le
    TLFi, au contraire de recopiage) il désigne l'action et non le résultat qui reste une copie. Si vous tenez au mot, dite alors "constructeur par recopie".

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par r0d
    J'ai donc supprimé, sur vos conseils, le constructeur de recopie et l'opérateur d'affectation.
    De quoi?

    Si tu as uniquement un objectif didactique, le plus intéressant serait peut-être d'analyser explicitement les différentes alternatives plutôt que d'en choisir une simplement parce que deux personnes sur un forum ont écrit qu'elle était meilleure.

  14. #14
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par r0d
    Faut-il implémenter 2 proxies? Un pour chaque?
    Les deux sont possibles.

  15. #15
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Bon, je n'ai plus trop le temps pour m'occuper de ça. Et puis elle est trés bien ma classe
    Allez hop -> bouclé.

  16. #16
    Membre éprouvé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Décembre 2005
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Décembre 2005
    Messages : 109
    Par défaut
    A la demande de r0d, je vais ajouter quelques unes des remarques que je lui ai proposé au sujet de la classe Dyn2DMatrix. (Je ne connaissais pas cette discussion en fait -_-)

    Il est a noté que j'ai eu des erreurs de compilation avec le code original. J'utilise mingw/g++ 3.4.5.
    J'ai fait quelques tests avec Visual C++ 2005, en désactivant les extensions du langage. Il accepte le code sans problème. Mes recherches et autres tests me font pourtant penser que c'est VC++ qui en fait trop. J'y reviendrai en temps utile.

    Méthode de présentation : code source original > explications > proposition de changement.

    ###################################################

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	size_t m_nbRow, m_nbCol;
    	std::vector<T> m_array;
    	T m_neutralElement;
    Il peut être intéressant de construire m_neutralElement avant de construire m_array. J'expliquerai ensuite pourquoi. Je propose donc une petite inversion.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	size_t m_nbRow, m_nbCol;
    	T m_neutralElement;
    	std::vector<T> m_array;
    ###################################################

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	Dyn2DMatrix()
    		: m_nbRow(0), m_nbCol(0), m_neutralElement(T())
    	{		
    	}
    Je ne vois vraiment pas l'intérêt d'utiliser le constructeur de copie pour construire m_neutralElement. Deux propositions, avec comme seule différence la verbosité (c'est français ?).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	Dyn2DMatrix()
    		: m_nbRow(0)
    		, m_nbCol(0)
    		, m_neutralElement()
    		, m_array()
    	{		
    	}
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	Dyn2DMatrix()
    		: m_nbRow(0)
    		, m_nbCol(0)
    	{		
    	}
    ###################################################

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	Dyn2DMatrix(const size_t nbRow, const size_t nbCol)
    		: m_nbRow(nbRow), m_nbCol(nbCol), m_neutralElement(T())
    	{
    		std::vector<T>::iterator it = m_array.begin();
    		m_array.insert(it, nbRow*nbCol, m_neutralElement);
    	}
    En plus des remarques précédentes, std::vector propose un constructeur prenant en paramètre le nombres d'élément et la valeur des éléments. Il n'y a aucune raison de ne pas utiliser l'existant, d'autant que ça diminue les sources d'erreur et optimise le code.
    Bien entendu il faut construire m_neutralElement avant, d'où la première modification.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	Dyn2DMatrix(const size_t nbRow, const size_t nbCol)
    		: m_nbRow(nbRow)
    		, m_nbCol(nbCol)
    		, m_neutralElement()
    		, m_array(nbRow*nbCol, m_neutralElement)
    	{
    	}
    ###################################################

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	Dyn2DMatrix(const size_t nbRow, const size_t nbCol, const T &neutralElement)
    		: m_nbRow(nbRow), m_nbCol(nbCol), m_neutralElement(neutralElement)
    	{
    		std::vector<T>::iterator it = m_array.begin();
    		m_array.insert(it, nbRow*nbCol, m_neutralElement);
    	}
    Même chose qu'au dessus.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	Dyn2DMatrix(const size_t nbRow, const size_t nbCol, const T &neutralElement)
    		: m_nbRow(nbRow)
    		, m_nbCol(nbCol)
    		, m_neutralElement(neutralElement)
    		, m_array(nbRow*nbCol, neutralElement)
    	{
    	}
    ###################################################

    Voila pour les constructeurs. La suite dans un autre post pour ne pas surcharger. Et après les fêtes si je n'ai pas le temps avant ^^

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 29/03/2007, 00h08
  2. Tableau à 2 dimensions avec utilisation de MALLOC
    Par johnalias110 dans le forum C
    Réponses: 3
    Dernier message: 28/02/2007, 18h54
  3. [Tableaux] Tableau à 2 dimensions: utilisation
    Par kurkaine dans le forum Langage
    Réponses: 3
    Dernier message: 11/01/2007, 20h14
  4. [débutant] un tableau de dimension variable selon l'objet qui le contient
    Par Epistocles dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 09/01/2007, 18h07
  5. [Tableaux] utilisation d'un tableau à deux dimensions
    Par calitom dans le forum Langage
    Réponses: 1
    Dernier message: 28/11/2006, 18h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo