Классы gslice и gslice_array: несколько диапазонов значений

Класс gslice позволяет задать сразу несколько диапазонов значений. Конструкторы класса:

gslice();
gslice(size_t start, const valarray<size_t> &sizes,
       const valarray<size_t> &strides);
gslice(const gslice &obj);

Параметр start задает начальный индекс, параметр sizes — количество элементов в виде объекта класса valarray, а параметр strides — шаг в виде объекта класса valarray. Получить эти значения после создания объекта позволяют методы start(), size() и stride(). Прототипы методов:

size_t start() const;
valarray<size_t> size() const;
valarray<size_t> stride() const;

Пример создания объекта и получения значений:

std::gslice obj(1, std::valarray<size_t>{2, 3},
                   std::valarray<size_t>{5, 1});
std::cout << obj.start() << std::endl;  // 1
std::valarray<size_t> sizes = obj.size();
for (size_t &el : sizes) std::cout << el << ' ';
std::cout << std::endl;                 // 2 3
std::valarray<size_t> strides = obj.stride();
for (size_t &el : strides) std::cout << el << ' ';
std::cout << std::endl;                 // 5 1

Для получения диапазона значений (среза) массива нужно указать объект класса gslice внутри квадратных скобок:

gslice_array<_Tp> operator[](const gslice &s);
valarray<_Tp> operator[](const gslice &s) const;

Результатом операции будет объект промежуточного класса gslice_array или объект, который может быть преобразован в объект valarray. Объявление класса gslice_array:

template<typename _Tp> class gslice_array;

В классе gslice_array доступен только конструктор копирования, поэтому создать объект этого класса другим способом нельзя. Для преобразования объекта класса gslice_array в массив нужно передать его конструктору класса valarray или выполнить присваивание (размеры объектов должны совпадать, иначе результат присваивания не определен). Пример:

std::gslice obj(1, std::valarray<size_t>{2, 3},
                   std::valarray<size_t>{5, 1});
std::valarray<int> arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::valarray<int> arr2 = arr1[obj];
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 2 3 4 7 8 9

Почему мы получили шесть элементов, а не пять? Ведь при сложении первого количества элементов (2) со вторым (3) вроде как получается 5. Давайте разберемся. Вначале определяются элементы первого среза. Мы указали 2 элемента с шагом 5. Это значения 2 и 7. Далее от этих двух значений отсчитываются элементы второго среза. Мы указали 3 элемента с шагом 1. Первые три элемента отсчитываются от первого элемента первого среза, а вторые три элемента — от второго элемента первого среза. Итого получается шесть элементов. Схематично это выглядит так:

arr1:    1 2 3 4 5 6 7 8 9 10
(2, 5):    *---------*
           |         |
(3, 1):    *-*-*     *-*-*
Итог:      2 3 4     7 8 9

Объект класса gslice_array содержит ссылки на элементы исходного массива. Все изменения этого объекта приведут к изменениям в исходном массиве. Например, присвоим нулевое значение всем элементам из среза:

std::gslice obj(1, std::valarray<size_t>{2, 3},
                   std::valarray<size_t>{5, 1});
std::valarray<int> arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
arr[obj] = 0;
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl; // 1 0 0 0 5 6 0 0 0 10

В классе gslice_array перегружены следующие операторы:

void operator=(const _Tp &n) const;
gslice_array &operator=(const gslice_array &s);
void operator=(const valarray<_Tp> &v) const;
void operator+=(const valarray<_Tp> &v) const;
void operator-=(const valarray<_Tp> &v) const;
void operator*=(const valarray<_Tp> &v) const;
void operator/=(const valarray<_Tp> &v) const;
void operator%=(const valarray<_Tp> &v) const;
void operator&=(const valarray<_Tp> &v) const;
void operator|=(const valarray<_Tp> &v) const;
void operator^=(const valarray<_Tp> &v) const;
void operator<<=(const valarray<_Tp> &v) const;
void operator>>=(const valarray<_Tp> &v) const;

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов