C++. Сборник рецептов
Шрифт:
Пример 11.27. Применение итератора kstride_iter
#include "kstride_iter.hpp"
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
int main {
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
kstride_iter<int*, 2> first(a);
kstride_iter<int*, 2> last(a + 8);
copy(first, last, ostream_iterator<int>(cout, "\n"));
}
11.14.
Проблема
Требуется реализовать числовые матрицы, размерности которых (количество строк и столбцов) неизвестны на этапе компиляции.
Решение
В примере 11.28 показана универсальная и эффективная реализация класса динамической матрицы, использующая итератор с шагом из рецепта 11.12 и
valarray
. Пример 11.28. matrix.hpp
#ifndef MATRIX_HPP
#define MATRIX_HPP
#include "stride_iter.hpp" // см. рецепт 11.12
#include <valarray>
#include <numeric>
#include <algorithm>
template<class Value_T>
class matrix {
public:
// открытые имена, вводимые typedef
typedef Value_T value_type;
typedef matrix self;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef Value_T* row_type;
typedef stride_iter<value_type*> col_type;
typedef const value_type* const_row_type;
typedef stride_iter<const value_type*> const_col_type;
// конструкторы
matrix : nrows(0), ncols(0), m {}
matrix(int r, int c) : nrows(r), ncols(c), m(r * с) {}
matrix(const self& x) : m(x.m), nrows(x.nrows), ncols(x.ncols) {}
template<typename T>
explicit matrix(const valarray<T>& x)
: m(x.size + 1), nrows(x.size), ncols(1) {
for (int i=0; i<x.size; ++i) m[i] = x[i];
}
// позволить конструирование из матриц других типов
template<typename T> explicit matrix(const matrix<T>& x)
: m(x.size + 1), nrows(x.nrows), ncols(x.ncols) {
copy(x.begin, x.end, m.begin);
}
// открытые функции
int rows const { return nrows; }
int cols const { return ncols; }
int size const { return nrows * ncols; }
//
доступ к элементам
row_type row begin(int n) { return &m[n * cols]; }
row_type row_end(int n) { return row_begin + cols; }
col_type col_begin(int n) { return col_type(&m[n], cols); }
col_type col_end(int n) { return col_begin(n) + cols; }
const_row_type row_begin(int n) const { return &m[n * cols]; }
const_row_type row_end(int n) const { return row_begin + cols; }
const_col_type col_begin(int n) const { return col_type(&m[n], cols); }
const_col_type col_end(int n) const { return col_begin + cols; }
iterator begin { return &m[0]; }
iterator end { return begin + size; }
const_iterator begin const { return &m[0]; }
const_iterator end const { return begin + size; }
// операторы
self& operator=(const self& x) {
m = x.m;
nrows = x.nrows;
ncols = x.ncols;
return *this;
}
self& operator=(value_type x) { m = x; return *this; }
row_type operator[](int n) { return row_begin(n); }
const_row_type operator[](int n) const { return row_begin(n); }
self& operator+=(const self& x) { m += x.m; return *this; }
self& operator-=(const self& x) { m -= x.m; return *this; }
self& operator+=(value_type x) { m += x; return *this; }
self& operator-=(value_type x) { m -= x; return *this; }
self& operator*=(value_type x) { m *= x; return *this; }
self& operator/=(value_type x) { m /= x; return *this; }
self& operator%=(value_type x) { m %= x; return *this; }
self operator- { return -m; }
self operator+ { return +m; }
self operator! { return !m; }
self operator~ { return ~m; }
// дружественные операторы
friend self operator+(const self& x, const self& y) { return self(x) += y; }
friend self operator-(const self& x, const self& y) { return self(x) -= y; }
friend self operator+(const self& x, value_type y) { return self(x) += y; }
friend self operator-(const self& x, value_type y) { return self(x) -= y; }
Поделиться с друзьями: