C++-Programmierung/ Eine Matrix-Bibliothek – mitrax/ proxy.hpp

Aus Wikibooks
Zur Navigation springen Zur Suche springen
Nuvola-inspired-terminal.svg
  1 #ifndef _mitrax_mitrax_proxy_hpp_INCLUDED_
  2 #define _mitrax_mitrax_proxy_hpp_INCLUDED_
  3 /// \file proxy.hpp
  4 ///
  5 /// \brief Proxyklassen für Zeilen und Spalten eines Matrixobjekts
  6 ///
  7 /// In dieser Datei werden die vier Proxyklassen definiert, welche jeweils ein Zeile oder Spalte
  8 /// einer konstante oder nicht-konstanten Matrix repräsentieren. Weiterhin steht hier die Funktion
  9 /// <code>element_swap()</code> welche alle Elemente zweier Zeilen oder Spalten miteinander
 10 /// vertauscht.
 11 
 12 #include "detail/proxy_iterator.hpp"
 13 #include "exception.hpp"
 14 
 15 namespace mitrax{
 16 
 17 // Forward-Deklarationen
 18 template < typename Matrix > class row_proxy;
 19 template < typename Matrix > class column_proxy;
 20 
 21 namespace detail{
 22 
 23 /// \brief Private Basisklasse für alle Proxys
 24 ///
 25 /// Diese Klasse enthält die Datenmember der Proxyklassen. Alle vier Proxyklassen werden direkt
 26 /// oder indirekt private von dieser Klasse angeleitet. Es ist nicht möglich Objekte von dieser
 27 /// Klasse zu erzeugen. Die Klasse ist eine Helferklasse mit der ein Benutzer keinen direkten
 28 /// Kontakt haben sollte.
 29 ///
 30 /// Compilergenrierte Methoden:
 31 ///   - Kopierkonstruktor
 32 ///   - Kopierzuweisung
 33 ///   - Destruktor
 34 template < typename Matrix >
 35 class line_const_proxy{
 36 protected:
 37     /// \brief Die Klasseninstanz des Klassentemplats matrix zu der der Proxy gehört
 38     typedef Matrix                      matrix_type;
 39     /// \brief Typ der Elemente der Matrix
 40     typedef typename Matrix::value_type value_type;
 41     /// \brief Typ der Dimensionselemente der Matrix
 42     typedef typename Matrix::size_type  size_type;
 43 
 44     /// \brief Konstruktor zur Objekterzeugung aus einem Verweis auf ein konstantes
 45     ///        <code>matrix</code>-Objekt und einer Zeilen-/Spaltennummer
 46     line_const_proxy(matrix_type const& matrix, size_type const& pos):
 47         matrix_(&matrix), pos_(pos){}
 48 
 49     /// \brief Lesezugriff auf die verwaltete Zeilen-/Spaltennummer
 50     size_type const pos()const{ return pos_; }
 51 
 52     /// \brief Lesezugriff auf die referenzierte Matrix
 53     matrix_type const& matrix_const()const{ return *matrix_; }
 54 
 55 private:
 56     /// \brief Die referenzierte Matrix
 57     matrix_type const* matrix_;
 58     /// \brief Die verwaltete Zeile/Spalte aus der Matrix
 59     size_type          pos_;
 60 };
 61 
 62 /// \brief Private Basisklasse für alle Proxys für nicht-konstante Matrizen
 63 ///
 64 /// Diese Klasse stellt das Matrixobjekt als nicht-konstante Referenz zu Verfügung. Alle
 65 /// Proxyklassen für nicht-konstante Matrizen werden private von dieser Klasse angeleitet. Es ist
 66 /// nicht möglich Objekte von dieser Klasse zu erzeugen. Die Klasse ist eine Helferklasse mit der
 67 /// ein Benutzer keinen direkten Kontakt haben sollte.
 68 ///
 69 /// Compilergenerierte Methoden:
 70 ///   - Kopierkonstruktor
 71 ///   - Kopierzuweisung
 72 ///   - Destruktor
 73 template < typename Matrix >
 74 class line_proxy: protected line_const_proxy< Matrix >{
 75 protected:
 76     /// \brief Die Klasseninstanz des Klassentemplats matrix zu der der Proxy gehört
 77     typedef Matrix                      matrix_type;
 78     /// \brief Typ der Elemente der Matrix
 79     typedef typename Matrix::value_type value_type;
 80     /// \brief Typ der Dimensionselemente der Matrix
 81     typedef typename Matrix::size_type  size_type;
 82 
 83     /// \brief Konstruktor zur Objekterzeugung aus einem Verweis auf <code>matrix</code>-Objekt und
 84     ///        einer Zeilen-/Spaltennummer
 85     line_proxy(matrix_type& matrix, size_type const& pos):
 86         detail::line_const_proxy< matrix_type >(matrix, pos){}
 87 
 88     /// \brief Schreibzugriff auf die referenzierte Matrix
 89     matrix_type& matrix()const{ return const_cast< matrix_type& >(this->matrix_const()); }
 90 };
 91 
 92 /// \brief Helfer zu Iteratorerzeugung in Zeilenproxys (<code>begin()</code>)
 93 template < typename Matrix, typename Iterator >
 94 inline
 95 Iterator const
 96 create_begin_row_iterator(
 97     Matrix& matrix,
 98     typename Matrix::size_type const& row
 99 ){
100     return Iterator(
101         matrix.begin() + (matrix.columns() * row)
102     );
103 }
104 
105 /// \brief Helfer zu Iteratorerzeugung in Zeilenproxys (<code>end()</code>)
106 template < typename Matrix, typename Iterator >
107 inline
108 Iterator const
109 create_end_row_iterator(
110     Matrix& matrix,
111     typename Matrix::size_type const& row
112 ){
113     return Iterator(
114         matrix.begin() + (matrix.columns() * (row + 1))
115     );
116 }
117 
118 
119 /// \brief Helfer zu Iteratorerzeugung in Spaltenproxys (<code>begin()</code>)
120 template < typename Matrix, typename Iterator >
121 inline
122 Iterator const
123 create_begin_column_iterator(
124     Matrix& matrix,
125     typename Matrix::size_type const& column
126 ){
127     return Iterator(
128         matrix,
129         column
130     );
131 }
132 
133 /// \brief Helfer zu Iteratorerzeugung in Spaltenproxys (<code>end()</code>)
134 template < typename Matrix, typename Iterator >
135 inline
136 Iterator const
137 create_end_column_iterator(
138     Matrix& matrix,
139     typename Matrix::size_type const& column
140 ){
141     return Iterator(
142         matrix,
143         column + matrix.columns() * matrix.rows()
144     );
145 }
146 
147 }
148 
149 /// \brief Proxyklasse die eine Zeile eines konstanten <code>matrix</code>-Objekts repräsentiert
150 template < typename Matrix >
151 class row_const_proxy: private detail::line_const_proxy< Matrix >{
152 public:
153     /// \brief Die Klasseninstanz des Klassentemplats <code>matrix</code> zu der der Proxy gehört
154     typedef Matrix                                    matrix_type;
155     /// \brief Typ der Elemente der Matrix
156     typedef typename Matrix::value_type               value_type;
157     /// \brief Iteratoren für Lesezugriff
158     typedef detail::row_const_iterator< matrix_type > const_iterator;
159     /// \brief Iteratoren für Lesezugriff
160     typedef const_iterator                            iterator;
161     /// \brief Typ der Dimensionselemente der Matrix
162     typedef typename Matrix::size_type                size_type;
163     /// \brief <code>difference_type</code> der Iteratoren
164     typedef typename const_iterator::difference_type  difference_type;
165 
166     /// \brief Objekterzeugung aus einem Verweis auf ein konstantes <code>matrix</code>-Objekt und
167     ///        einer Zeilennummer
168     row_const_proxy(matrix_type const& matrix, size_type const& row):
169         detail::line_const_proxy< matrix_type >(matrix, row){}
170 
171     /// \brief Lesezugriff auf das Element <code>column_number</code>
172     ///
173     /// siehe <code>column()</code>
174     value_type const&
175     operator[](size_type const& column_number)const{ return column(column_number); }
176     /// \brief Lesezugriff auf das Element number
177     value_type const& column(size_type const& number)const{ return *(begin() + number); }
178 
179     /// \brief Anzahl der Spalten
180     size_type const columns()const{ return this->matrix_const().columns(); }
181     /// \brief Anzahl der Spalten
182     ///
183     /// siehe <code>columns()</code>
184     size_type const size()const{ return columns(); }
185 
186     /// \brief Zeile die das Objekt repräsentiert
187     size_type const pos()const{ return detail::line_const_proxy< matrix_type >::pos(); }
188 
189     /// \brief Leseiterator auf das erste Element
190     const_iterator const begin()const{ return cbegin(); }
191 
192     /// \brief Leseiterator hinter das letzte Element
193     const_iterator const end()const{ return cend(); }
194 
195     /// \brief Leseiterator auf das erste Element
196     const_iterator const cbegin()const{
197         return detail::create_begin_row_iterator< matrix_type const, const_iterator >(
198             this->matrix_const(), pos()
199         );
200     }
201 
202     /// \brief Leseiterator hinter das letzte Element
203     const_iterator const cend()const{
204         return detail::create_end_row_iterator< matrix_type const, const_iterator >(
205             this->matrix_const(), pos()
206         );
207     }
208 };
209 
210 /// \brief Proxyklasse die eine Spalte eines konstanten <code>matrix</code>-Objekts repräsentiert
211 template < typename Matrix >
212 class column_const_proxy: private detail::line_const_proxy< Matrix >{
213 public:
214     /// \brief Die Klasseninstanz des Klassentemplats <code>matrix</code> zu der der Proxy gehört
215     typedef Matrix                                       matrix_type;
216     /// \brief Typ der Elemente der Matrix
217     typedef typename Matrix::value_type                  value_type;
218     /// \brief Iteratoren für Lesezugriff
219     typedef detail::column_const_iterator< matrix_type > const_iterator;
220     /// \brief Iteratoren für Lesezugriff
221     typedef const_iterator                               iterator;
222     /// \brief Typ der Dimensionselemente der Matrix
223     typedef typename Matrix::size_type                   size_type;
224     /// \brief <code>difference_type</code> der Iteratoren
225     typedef typename const_iterator::difference_type     difference_type;
226 
227     /// \brief Objekterzeugung aus einem Verweis auf ein konstantes <code>matrix</code>-Objekt und
228     ///        einer Spaltennummer
229     column_const_proxy(matrix_type const& matrix, size_type const& column):
230         detail::line_const_proxy< matrix_type >(matrix, column){}
231 
232     /// \brief Lesezugriff auf das Element <code>row_number</code>
233     ///
234     /// siehe <code>row()</code>
235     value_type const& operator[](size_type const& row_number)const{ return row(row_number); }
236     /// \brief Lesezugriff auf das Element number
237     value_type const& row(size_type const& number)const{ return *(begin() + number); }
238 
239     /// \brief Anzahl der Zeilen
240     size_type const rows()const{ return this->matrix_const().rows(); }
241     /// \brief Anzahl der Zeilen
242     ///
243     /// siehe <code>rows()</code>
244     size_type const size()const{ return rows(); }
245 
246     /// \brief Spalte die das Objekt repräsentiert
247     size_type const pos()const{ return detail::line_const_proxy< matrix_type >::pos(); }
248 
249     /// \brief Leseiterator auf das erste Element
250     const_iterator const begin()const{ return cbegin(); }
251 
252     /// \brief Leseiterator hinter das letzte Element
253     const_iterator const end()const{ return cend(); }
254 
255     /// \brief Leseiterator auf das erste Element
256     const_iterator const cbegin()const{
257         return detail::create_begin_column_iterator< matrix_type const, const_iterator >(
258             this->matrix_const(), pos()
259         );
260     }
261 
262     /// \brief Leseiterator hinter das letzte Element
263     const_iterator const cend()const{
264         return detail::create_end_column_iterator< matrix_type const, const_iterator >(
265             this->matrix_const(), pos()
266         );
267     }
268 };
269 
270 
271 /// \brief Proxyklasse die eine Zeile eines <code>matrix</code>-Objekts repräsentiert
272 template < typename Matrix >
273 class row_proxy: private detail::line_proxy< Matrix >{
274 public:
275     /// \brief Die Klasseninstanz des Klassentemplats <code>matrix</code> zu der der Proxy gehört
276     typedef Matrix                                                   matrix_type;
277     /// \brief Typ der Elemente der Matrix
278     typedef typename Matrix::value_type                              value_type;
279     /// \brief Iteratoren für Lesezugriff
280     typedef typename row_const_proxy< matrix_type >::const_iterator  const_iterator;
281     /// \brief Iteratoren für Schreibzugriff
282     typedef detail::row_iterator< matrix_type >                      iterator;
283     /// \brief Typ der Dimensionselemente der Matrix
284     typedef typename Matrix::size_type                               size_type;
285     /// \brief <code>difference_type</code> der Iteratoren
286     typedef typename row_const_proxy< matrix_type >::difference_type difference_type;
287 
288     /// \brief Objekterzeugung aus einem Verweis auf ein <code>matrix</code>-Objekt und einer
289     ///        Zeilennummer
290     row_proxy(matrix_type& matrix, size_type const& row):
291         detail::line_proxy< matrix_type >(matrix, row){}
292 
293     /// \brief Schreibzugriff auf das Element <code>column_number</code>
294     ///
295     /// siehe <code>column()</code>
296     value_type& operator[](size_type const& column_number)const{ return column(column_number); }
297     /// \brief Schreibzugriff auf das Element <code>number</code>
298     value_type& column(size_type const& number)const{ return *(begin() + number); }
299 
300     /// \brief Anzahl der Spalten
301     size_type const columns()const{ return this->matrix_const().columns(); }
302     /// \brief Anzahl der Spalten
303     ///
304     /// siehe <code>columns()</code>
305     size_type const size()const{ return columns(); }
306 
307     /// \brief Zeile die das Objekt repräsentiert
308     size_type const pos()const{ return detail::line_proxy< matrix_type >::pos(); }
309 
310 
311     /// \brief Schreibiterator auf das erste Element
312     iterator const begin()const{
313         return detail::create_begin_row_iterator< matrix_type, iterator >(this->matrix(), pos());
314     }
315 
316     /// \brief Schreibiterator hinter das letzte Element
317     iterator const end()const{
318         return detail::create_end_row_iterator< matrix_type, iterator >(this->matrix(), pos());
319     }
320 
321     /// \brief Leseiterator auf das erste Element
322     const_iterator const cbegin()const{
323         return detail::create_begin_row_iterator< matrix_type const, const_iterator >(
324             this->matrix_const(), pos()
325         );
326     }
327 
328     /// \brief Leseiterator hinter das letzte Element
329     const_iterator const cend()const{
330         return detail::create_end_row_iterator< matrix_type const, const_iterator >(
331             this->matrix_const(), pos()
332         );
333     }
334 
335     /// \brief Typumwandlung in <code>row_const_proxy< matrix_type ></code>
336     operator row_const_proxy< matrix_type >()const{
337         return row_const_proxy< matrix_type >(this->matrix_const(), this->pos());
338     }
339 };
340 
341 /// \brief Proxyklasse die eine Spalte eines konstanten <code>matrix</code>-Objekts repräsentiert
342 template < typename Matrix >
343 class column_proxy: private detail::line_proxy< Matrix >{
344 public:
345     /// \brief Die Klasseninstanz des Klassentemplats <code>matrix</code> zu der der Proxy gehört
346     typedef Matrix                                                      matrix_type;
347     /// \brief Typ der Elemente der Matrix
348     typedef typename Matrix::value_type                                 value_type;
349     /// \brief Iteratoren für Lesezugriff
350     typedef typename column_const_proxy< matrix_type >::const_iterator  const_iterator;
351     /// \brief Iteratoren für Schreibzugriff
352     typedef detail::column_iterator< matrix_type >                      iterator;
353     /// \brief Typ der Dimensionselemente der Matrix
354     typedef typename Matrix::size_type                                  size_type;
355     /// \brief <code>difference_type</code> der Iteratoren
356     typedef typename column_const_proxy< matrix_type >::difference_type difference_type;
357 
358     /// \brief Objekterzeugung aus einem Verweis auf ein <code>matrix</code>-Objekt und einer
359     ///        Spaltennummer
360     column_proxy(matrix_type& matrix, size_type const& column):
361         detail::line_proxy< matrix_type >(matrix, column){}
362 
363     /// \brief Schreibzugriff auf das Element <code>row_number</code>
364     ///
365     /// siehe <code>row()</code>
366     value_type& operator[](size_type const& row_number)const{ return row(row_number); }
367     /// \brief Schreibzugriff auf das Element number
368     value_type& row(size_type const& number)const{ return *(begin() + number); }
369 
370     /// \brief Anzahl der Zeilen
371     size_type const rows()const{ return this->matrix_const().rows(); }
372     /// \brief Anzahl der Zeilen
373     ///
374     /// siehe <code>rows()</code>
375     size_type const size()const{ return rows(); }
376 
377     /// \brief Spalte die das Objekt repräsentiert
378     size_type const pos()const{ return detail::line_proxy< matrix_type >::pos(); }
379 
380     /// \brief Schreibiterator auf das erste Element
381     iterator const begin()const{
382         return detail::create_begin_column_iterator< matrix_type, iterator >(
383             this->matrix(), pos()
384         );
385     }
386 
387     /// \brief Schreibiterator hinter das letzte Element
388     iterator const end()const{
389         return detail::create_end_column_iterator< matrix_type, iterator >(this->matrix(), pos());
390     }
391 
392     /// \brief Leseiterator auf das erste Element
393     const_iterator const cbegin()const{
394         return detail::create_begin_column_iterator< matrix_type const, const_iterator >(
395             this->matrix_const(), pos()
396         );
397     }
398 
399     /// \brief Leseiterator hinter das letzte Element
400     const_iterator const cend()const{
401         return detail::create_end_column_iterator< matrix_type const, const_iterator >(
402             this->matrix_const(), pos()
403         );
404     }
405 
406     /// \brief Typumwandlung in <code>column_const_proxy< matrix_type ></code>
407     operator column_const_proxy< matrix_type >()const{
408         return column_const_proxy< matrix_type >(this->matrix_const(), this->pos());
409     }
410 };
411 
412 
413 
414 namespace detail{
415 
416 /// \brief Helferfunktion für <code>element_swap()</code>
417 template < typename Proxy >
418 inline
419 void
420 element_swap_template(
421     Proxy const& lhs,
422     Proxy const& rhs
423 ){
424     typedef typename Proxy::iterator iterator;
425     using std::swap;
426 
427     // kompatibilität prüfen
428     if(lhs.size() != rhs.size()){
429         throw error::size_unequal("mitrax::element_swap_template<>()", lhs.size(), rhs.size());
430     }
431 
432     // Elementweise tauschen
433     for(
434         iterator i = lhs.begin(), j = rhs.begin();
435         i != lhs.end();
436         ++i, ++j
437     ){
438         swap(*i, *j);
439     }
440 }
441 
442 }
443 
444 /// \brief Vertauscht Elemente zweier Zeilen
445 template < typename Matrix >
446 inline
447 void
448 element_swap(row_proxy< Matrix > const& lhs, row_proxy< Matrix > const& rhs){
449     detail::element_swap_template(lhs, rhs);
450 }
451 
452 /// \brief Vertauscht Elemente zweier Spalten
453 template < typename Matrix >
454 inline
455 void
456 element_swap(column_proxy< Matrix > const& lhs, column_proxy< Matrix > const& rhs){
457     detail::element_swap_template(lhs, rhs);
458 }
459 
460 
461 }
462 
463 #endif