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.