Архитектурная акустика/Реализация/IteratorAdapter2D

Материал из CAMaaS preliminary wiki
Перейти к навигации Перейти к поиску

Итератор-адаптер, позволяющий перечислять элементы двумерных контейнеров как одномерных.

template <class _OuterIterator, class _InnerIterator = /*См. описание*/>
class IteratorAdapter2D;
_OuterIteratorТип внешнего итератора (первое измерение). Тип typename std::iterator_traits<_OuterIterator>::value_type (см. std::iterator_traits) должен удовлетворять требованиям Container.
_InnerIteratorТип вложенного итератора (второе измерение). По умолчанию тип определяется следующим образом.

Если тип _OuterIterator является обратным итератором, т.е. является специализацией шаблонов std::reverse_iterator или Chusov::Math::MatrixColumnReverseIterator, то тип _InnerIterator по умолчанию является типом возвращаемого значения метода rbegin (без параметров) класса _OuterIterator.

В противном случае тип _InnerIterator по умолчанию является типом возвращаемого значения метода begin (без параметров) класса _OuterIterator.

Если соответствующий метод не реализуется, то использование типа по умолчанию для _InnerIterator приводит к жесткой ошибке компиляции (без SFINAE).
Открытые типы
ТипОписание
outer_iteratorТип _OuterIterator.
inner_iteratorТип _InnerIterator.
iterator_categoryКатегория итератора. Эквивалентен
std::common_type_t<
    typename std::iterator_traits<outer_iterator>::iterator_category,
    typename std::iterator_traits<inner_iterator>::iterator_category
>
value_typeТип typename std::iterator_traits<inner_iterator>::value_type.
referenceТип typename std::iterator_traits<inner_iterator>::reference.
pointerТип typename std::iterator_traits<inner_iterator>::pointer.
difference_typeТип разницы между позициями итератора. Эквивалентен
std::common_type_t<
    typename std::iterator_traits<outer_iterator>::difference_type,
    typename std::iterator_traits<inner_iterator>::difference_type
>
Открытые методы
Методы, определенные, если тип iterator_category задает прямой итератор.
МетодОписание
(конструкторы)Конструкторы класса IteratorAdapter2D.
(деструктор)Деструктор класса IteratorAdapter2D.
operator=Операторы присваивания с копированием и перемещением.
operator*Оператор разыменовывания.
operator->Оператор косвенного доступа к элементам.
operator++Сдвиг позиции итератора на единицу от начала.
operator==Проверка на эквивалентность итераторов.
operator!=Проверка на неэквивалентность итераторов.
outer_baseДоступ к итератору в первом измерении, в соответствии с текущей позицией IteratorAdapter2D.
inner_baseДоступ к итератору во втором измерении, в соответствии с текущей позицией IteratorAdapter2D.
Методы, определенные, если тип iterator_category также задает двунаправленный итератор.
МетодОписание
operator--Сдвиг позиции итератора на единицу к началу.
Методы, определенные, если тип iterator_category также задает итератор с произвольным доступом.
МетодОписание
operator+=Изменение позиции итератора на заданное число элементов к концу.
operator-=Изменение позиции итератора на заданное число элементов к началу.
operator+Возвращает итератор, сдвинутый к концу относительно текущего на заданное число позиций.
operator-Возвращает итератор, сдвинутый к началу относительно текущего на заданное число позиций, либо расстояние между двумя итераторами.
operator[]Возвращает элемент, находящийся на заданном расстоянии относительно позиции итератора.
operator<Проверка на то, чтобы текущий итератор находился ближе к началу контейнера по сравнению с итератором, который указан параметром.
operator<=Проверка на то, чтобы текущий итератор находился ближе к началу контейнера по сравнению с итератором, который указан параметром, либо совпадал с ним.
operator>Проверка на то, чтобы текущий итератор находился дальше от начала контейнера по сравнению с итератором, который указан параметром.
operator>=Проверка на то, чтобы текущий итератор находился дальше от начала контейнера по сравнению с итератором, который указан параметром, либо совпадал с ним.
Защищенные методы
Методы, определенные, если тип iterator_category задает прямой итератор.
МетодОписание
get_it2Возвращает указатель на реализацию итератора IteratorAdapter2D::inner_iterator в текущей позиции или нулевой адрес, или, если текущая позиция итератора в первом измерении либо позиция итератора во втором измерении не соответствуют действительному элементу контейнера.
reset_it2Устанавливает новое состояние для итератора во втором измерении.
Защищенные данные
Члены, определенные, если тип iterator_category задает прямой итератор.
Элемент данныхОписание
m_it1Текущий итератор в первом измерении.
Функции, не являющиеся частью определения класса
Если тип iterator_category задает итератор с произвольным доступом.
ФункцияОписание
operator+Создает копию указанного итератора IteratorAdapter2D, сдвинутую относительно него на заданное число позиций.

Для итераторов типа IteratorAdapter2D существуют следующие ограничения. Пусть c - двумерный контейнер, по элементам которого производится перечисление.

  1. Итератор инкрементируем, только если он принадлежит полуинтервалу [make_iterator_adapter<IteratorAdapter2D>(c.begin()), make_iterator_adapter<IteratorAdapter2D>(c.end())).
  2. Итератор декрементируем, только если он принадлежит полуинтервалу (make_iterator_adapter<IteratorAdapter2D>(c.begin()), make_iterator_adapter<IteratorAdapter2D>(c.end())].
  3. Итератор дереференцируем, только если он инкрементируем, и двумерный контейнер не пуст ни в одном из измерений. Если же двумерный контейнер пуст во втором измерении, но не пуст в первом, то итераторы из полуинтервала [make_iterator_adapter<IteratorAdapter2D>(c.begin()), make_iterator_adapter<IteratorAdapter2D>(c.end())) инкрементируемы, но не дереференцируемы.
Пример
std::vector<std::vector<int>> vv;
vv.emplace_back(std::vector<int>({1, 2, 3}));
vv.emplace_back(std::vector<int>({4, 5, 6}));
vv.emplace_back(std::vector<int>({7, 8, 9}));
std::cout << "Vector of vectors - full sequence: ";
for (auto it = make_iterator_adapter<IteratorAdapter2D>(vv.begin()); it != vv.end(); ++it)
    std::cout << *it << " ";
std::cout << "\nVector of vectors - middle elements (access through the adapter): ";
for (auto it = make_iterator_adapter<IteratorAdapter2D>(vv.begin()) + 3; it < make_iterator_adapter<IteratorAdapter2D>(vv.end()) - 3; ++it)
    std::cout << *it << " ";
std::cout << "\nVector of vectors - middle elements (construction of adapters with specified nested iterators): ";
for (auto it = make_iterator_adapter<IteratorAdapter2D>(vv.begin() + 1, (vv.begin() + 1)->begin()); 
    it != make_iterator_adapter<IteratorAdapter2D>(vv.end() - 2, (vv.end() - 2)->end()); ++it)
    std::cout << *it << " ";
std::cout << "\nTotal size of the vector is " << make_iterator_adapter<IteratorAdapter2D>(vv.end()) - vv.begin() << " int\'s.";
std::vector<std::vector<int>> vv_empty_2nd(10);
std::cout << "\nTotal size of a vector with zero-size second dimension is " << make_iterator_adapter<IteratorAdapter2D>(vv_empty_2nd.end()) - 
    vv_empty_2nd.begin() << " int\'s.";
std::vector<std::vector<int>> vv_empty;
std::cout << "\nTotal size of a vector with no elements at all " << make_iterator_adapter<IteratorAdapter2D>(vv_empty.end()) - 
    vv_empty.begin() << " int\'s.";
Пример
using namespace Chusov::Math;
Matrix<double> m = 
{
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};
std::cout << "\nSequentialized matrix elements (direct range construction): ";
for (auto&& elem:Chusov::Memory::make_iterator_range(make_iterator_adapter<IteratorAdapter2D>(m.begin()), make_iterator_adapter<IteratorAdapter2D>(m.end())))
    std::cout << elem << " ";
std::cout << "\nSequentialized matrix elements (range adaption): ";
for (auto&& elem:adapt_iterator_range<IteratorAdapter2D>(m.begin(), m.end()))
    std::cout << elem << " ";