Зачем нужен iterator traits
Перейти к содержимому

Зачем нужен iterator traits

  • автор:

Структура iterator_traits

Вспомогательная структура-шаблон, используется для указания всех критических определений типов, которые должен иметь итератор.

Синтаксис

struct iterator_traits < typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef difference_type distance_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; >; 

Замечания

Структура-шаблон определяет типы элементов

  • iterator_category : синоним для Iterator::iterator_category .
  • value_type : синоним для Iterator::value_type .
  • difference_type : синоним для Iterator::difference_type .
  • distance_type : синоним для Iterator::difference_type.
  • pointer : синоним для Iterator::pointer .
  • reference : синоним для Iterator::reference .

Частичные специализации определяют критические типы, связанные с указателем на объект типа тип * или const тип *.

В этой реализации вы также можете применить несколько шаблонов функций, которые не используют частичную специализацию:

template C _Iter_cat(const iterator&); template random_access_iterator_tag _Iter_cat(const Ty *); template Ty *val_type(const iterator&); template Ty *val_type(const Ty *); template Diff *_Dist_type(const iterator&); template ptrdiff_t *_Dist_type(const Ty *); 

что определяет некоторые из тех же типов более косвенно. Используйте эти функции как аргументы для вызова функции. Их единственной целью является предоставление полезного параметра шаблона класса вызываемой функции.

Пример

// iterator_traits.cpp // compile with: /EHsc #include #include #include #include using namespace std; template < class it >void function( it i1, it i2 ) < iterator_traits::iterator_category cat; cout << typeid( cat ).name( ) << endl; while ( i1 != i2 ) < iterator_traits::value_type x; x = *i1; cout ; cout ; int main( ) < vectorvc( 10,'a' ); list li( 10 ); function( vc.begin( ), vc.end( ) ); function( li.begin( ), li.end( ) ); > /* Output: struct std::random_access_iterator_tag a a a a a a a a a a struct std::bidirectional_iterator_tag 0 0 0 0 0 0 0 0 0 0 */ 

Требования

Заголовок:

Пространство имен: std

Зачем нужен iterator traits

Определяет предопределенные итераторы итераторы потоков, примитивы итератора и вспомогательные шаблоны.

Требования

Заголовок.

Пространство имен std :

Замечания

Итераторы — это обобщение указателей, которые позволяют программе C++ работать с различными структурами данных в однородном режиме. Вместо того чтобы работать с определенными типами данных, алгоритмы работают с диапазоном значений, как указано типом итератора. Алгоритмы могут работать с любой структурой данных, удовлетворяющей требованиям итератора.

В C++20 есть шесть категорий итераторов. Итераторы упорядочены в иерархии возможностей. Их возможности задаются концепциями C++20. Описание различных итераторов и их возможностей см . в разделе «Основные понятия итератора»

Visual Studio добавил расширения в итераторы стандартной библиотеки C++ для поддержки отладки для проверка и не проверка итераторов. Дополнительные сведения см. в разделе Безопасные библиотеки: стандартная библиотека C++.

Участники

Функции

Имя Описание
advance Увеличивает итератор на указанное количество позиций.
back_inserter Создает итератор, может вставлять элементы с обратной стороны указанного контейнера.
begin Извлекает итератор для первого элемента в указанном контейнере.
cbegin Извлекает итератор только для чтения в первый элемент в указанном контейнере.
cend Извлекает итератор только для чтения в элемент, который следует последнему элементу в указанном контейнере.
crbegin Получите обратный итератор только для чтения до начала указанного контейнера.
crend Получите sentinel в конце возвращаемого crbegin() значения.
data Получите указатель на первый элемент в указанном контейнере.
distance Указывает количество приращений между позициями, которые адресуют два итератора.
end Извлекает итератор для элемента, следующего за последним элементом в указанном контейнере.
empty Проверьте, пуст ли указанный контейнер.
front_inserter Создает итератор, может вставлять элементы с передней стороны указанного контейнера.
inserter Адаптер итератора, добавляющий в контейнер новый элемент в указанной позиции.
make_checked_array_iterator Создает объект checked_array_iterator , который можно использовать другими алгоритмами. Примечание. Эта функция — расширение Майкрософт для стандартной библиотеки C++. Код, реализованный с помощью этой функции, не переносимый в среды сборки C++ Standard, которые не поддерживают это расширение Майкрософт.
make_move_iterator Возвращает итератор перемещения, содержащий предоставленный итератор в качестве сохраненного базового итератора.
make_unchecked_array_iterator Создает объект unchecked_array_iterator , который можно использовать другими алгоритмами. Примечание. Эта функция — расширение Майкрософт для стандартной библиотеки C++. Код, реализованный с помощью этой функции, не переносимый в среды сборки C++ Standard, которые не поддерживают это расширение Майкрософт.
next Выполняет итерацию заданное число раз и возвращает новую позицию итератора.
prev Выполняет обратную итерацию заданное число раз и возвращает новую позицию итератора.
rbegin Получите обратный итератор к началу указанного контейнера.
rend Получите обратный итератор в sentinel в конце указанного контейнера.
size Получение количества элементов.

Операторы

Имя Описание
operator!= Проверяет, не равен ли объект итератора слева от оператора итератору справа.
operator== Проверяет объект итератора в левой части оператора на равенство объекту итератора в правой части.
operator< Определяет, верно ли, что объект итератора в левой части оператора меньше объекта итератора в правой части.
operator

Определяет, верно ли, что объект итератора в левой части оператора меньше или равен объекту итератора в правой части.
operator> Определяет, верно ли, что объект итератора в левой части оператора больше объекта итератора в правой части.
operator>= Определяет, верно ли, что объект итератора в левой части оператора больше или равен объекту итератора в правой части.
operator+ Добавление смещения к итератору и возврат нового итератора reverse_iterator , который обращается к вставленному элементу в новой позиции смещения.
operator- Вычитает один итератор из другого и возвращает разницу.

Классы

Имя Описание
back_insert_iterator Шаблон класса описывает выходной итератор объекта. Он вставляет элементы в контейнер типа Container , к которому он обращается через защищенный pointer объект, который он хранит, называется контейнером.
bidirectional_iterator_tag Класс, предоставляющий тип возвращаемого значения для iterator_category функции, представляющей двунаправленный итератор.
checked_array_iterator Класс, который обращается к массиву при помощи проверенного итератора произвольного доступа. Примечание. Этот класс — расширение Майкрософт для стандартной библиотеки C++. Код, реализованный с помощью этой функции, не переносимый в среды сборки C++ Standard, которые не поддерживают это расширение Майкрософт.
forward_iterator_tag Класс, предоставляющий тип возвращаемого значения для iterator_category функции, представляющей итератор пересылки.
front_insert_iterator Шаблон класса описывает выходной итератор объекта. Он вставляет элементы в контейнер типа Container , к которому он обращается через защищенный pointer объект, который он хранит, называется контейнером.
input_iterator_tag Класс, предоставляющий тип возвращаемого значения для iterator_category функции, представляющей входной итератор.
insert_iterator Шаблон класса описывает выходной итератор объекта. Он вставляет элементы в контейнер типа Container , к которому он обращается через защищенный pointer объект, который он хранит, называется контейнером. Он также сохраняет защищенный iterator объект класса Container::iterator , называемый iter .
istream_iterator Шаблон класса описывает входной итераторный объект. Он извлекает объекты класса Ty из входного потока, к которому он обращается через объект, на который он хранит, указателя basic_istream типа.
istreambuf_iterator Шаблон класса описывает входной итераторный объект. Он вставляет элементы класса Elem в выходной буфер потока, к которому он обращается через объект, в котором он хранит тип pointer basic_streambuf .
iterator Шаблон класса используется в качестве базового типа для всех итераторов.
iterator_traits Вспомогательный класс шаблона, предоставляющий критические типы, связанные с разными типами итераторов, на которые они могут ссылаться аналогичным образом.
move_iterator Объект move_iterator содержит итератор произвольного доступа типа RandomIterator . Его поведение аналогично поведению итератора произвольного доступа, кроме случаев отмены ссылки. Результат operator* неявно приводится к value_type&&: , чтобы обеспечить rvalue reference .
ostream_iterator Шаблон класса описывает выходной итератор объекта. Он вставляет объекты класса Type в выходной поток, к которому он обращается через объект, в котором он хранит тип pointer basic_ostream .
ostreambuf_iterator Шаблон класса описывает выходной итератор объекта. Он вставляет элементы класса Elem в выходной буфер потока, к которому он обращается через объект, на который он хранит, указателя basic_streambuf типа.
output_iterator_tag Класс, предоставляющий тип возвращаемого значения для iterator_category функции, представляющей итератор выходных данных.
random_access_iterator_tag Класс, предоставляющий тип возвращаемого значения для iterator_category функции, представляющей итератор случайного доступа.
reverse_iterator Шаблон класса описывает объект, который ведет себя как итератор случайного доступа, только в обратном направлении.
unchecked_array_iterator Класс, который обращается к массиву при помощи непроверенного итератора произвольного доступа. Примечание. Этот класс — расширение Майкрософт для стандартной библиотеки C++. Код, реализованный с помощью этой функции, не переносимый в среды сборки C++ Standard, которые не поддерживают это расширение Майкрософт.

Основные понятия

В пространстве имен определены std следующие понятия. Они применяются к итераторам, а также относятся к категориям итератора для диапазонов, описанных в концепциях.

Концепция итератора Description
bidirectional_iterator C++20 Указывает итератор, который может считывать и записывать как вперед, так и назад.
contiguous_iterator C++20 Указывает итератор, элементы которого являются последовательными в памяти, одинаковым размером и могут быть доступны с помощью арифметики указателя.
forward_iterator C++20 Указывает итератор, который может читать (и, возможно, записывать) несколько раз.
input_iterator C++20 Указывает итератор, который можно прочитать по крайней мере один раз.
input_or_output_iterator C++20 Основа итеромии концепции таксономии.
output_iterator Указывает итератор, в который можно написать.
random_access_iterator C++20 Указывает итератор, который можно читать и записывать по индексу.
sentinel_for C++20 Указывает sentinel для типа итератора.
sized_sentinel_for C++20 Указывает, что итератор и его sentinel можно вычитать (используя — ), чтобы найти их разницу в постоянном времени.

Трейты — PHP: Погружаясь в классы

Трейты — альтернативный механизм переиспользования общего кода в разных классах. Он устраняет ограничения, которыми обладает наследование и заменяет его.

Трейты похожи на абстрактные классы. Они реализуют какую-то общую функциональность и с ними нельзя работать напрямую. Единственный способ использовать их – включение в другие классы.

 // Magic.php trait Magic  // Доступно только внутри трейта private $properties; public function __get($key)  return $this->properties[$key] ?? null; > public function __set($key, $value)  $this->properties[$key] = $value; > > 

Трейт по большей части выглядит как (абстрактный) класс и устроен как класс. Он подчиняется тем же правилам именования и расположения в иерархии пространств имён (а следовательно и файловой структуре) что и классы. Отличия начинаются в момент использования:

 // Config.php class Config  // Включение трейта в класс use Magic; > $config = new Config(); $config->key = 'value'; echo $config->key; 

Трейт включается в другой класс с помощью инструкции use . С этого момента в классе становится доступна вся функциональность, определённая в трейте. Но при этом трейт не встраивается в цепочку наследования, это легко проверить:

 $config instanceof Magic; // false 

Из этого есть пара важных следствий:

  • Внутри класса к методам трейта нельзя обратиться через parent , только через $this
  • Трейт не может реализовывать интерфейс. Это могут делать только классы.

Зачем?

Трейты в отличие от наследования, не фиксируют структуру классов. Любой класс может включать в себя любое количество трейтов:

 class MySuperClass  use FirstTrait; // При включении возможны конфликты имён. Подробнее про их разрешение: // https://www.php.net/manual/ru/language.oop5.traits.php#language.oop5.traits.conflict use SecondTrait; > 

Эта структура располагает к выделению общих признаков из совершенно разнообразных классов. Пример с Magic как раз хорошо демонстрирует такой подход. Многие классы одинаково реализуют магические методы и нет смысла дублировать их код. И точно не стоит использовать наследование, так как оно свяжет совершенно несвязанные классы в общую (и жёсткую) иерархию.

Трейты позволяют реализовать многие интерфейсы PHP универсальным образом, например, ArrayAccess или Iterator

Пример: Итератор

Рассмотрим готовый пример трейта-итератора. Он реализует общую логику обхода коллекций внутри объектов. С его помощью можно сделать объекты, которые можно использовать в foreach :

 // Реализует итератор $course = new Course(); foreach ($course as $lesson)  echo "$lesson\n"; > 
 trait IteratorTrait  protected $offset = 0; public function current()  return $this->getCollection()[$this->offset] ?? null; > public function next()  $this->offset++; > public function key()  return $this->offset; > public function valid()  return array_key_exists($this->offset, $this->getCollection()); > public function rewind()  $this->offset = 0; > abstract public function getCollection(); > 

Обратите внимание на важную деталь — трейт получает саму коллекцию. Трейт требует от класса, который его включает, реализации метода getCollection() (помните, что трейт похож на абстрактный класс, он может определять абстрактные методы). Этот метод используется внутри трейта для доступа к элементам коллекции, по которой он итерирует.

Это очень важная концепция. Трейту нужны данные от класса, в который его включают. И трейт строит связь с этими классами через интерфейсный метод, а не через обращение к свойству с конкретным именем. А вот класс от трейта ничего не требует. Благодаря тому, что связь строится в одну сторону (трейт зависит от метода класса, но класс не зависит от методов и свойств трейта), код остаётся модульным. Если бы и трейт требовал что-то от класса и класс от трейта, то почти наверняка в коде проблемы с архитектурой.

 // Обязательно реализовать интерфейс Iterator, только тогда PHP поймёт, что это итератор class Course implements Iterator  // Для простоты свойство наполнено строками private $lessons = ['one', 'two', 'three']; use IteratorTrait; protected function getCollection()  return $this->lessons; > > // Использование $course = new Course(); foreach ($course as $lesson)  echo "$lesson\n"; > // 'one' 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Объясните пожалуйста зачем нужна структура класса iterator_traits.

Author24 — интернет-сервис помощи студентам

Объясните, пожалуйста, зачем в C++ нужны указатели
Никак что-то не пойму, зачем в C++ указатели? Ведь можно спокойно программировать без них.

Объясните зачем нужна данная функция
Довольно односложный вопрос. Когда и зачем используется данная функция (соответственно, что будет.

Зачем присваивать переменной disc ноль? Объясните пожалуйста
Зачем присваивать disc = 0 (см. 9 строчку кода: double oplata, disc=0; Препод говорит что нужен.

Объясните пожалуйста зачем при авторизации создавать новую сессию
Всем доброго! Подскажите пож-та в чем разница между 2-мя подходами и какой правильнее: 1. При.

Ушел с форума

Эксперт С++

16472 / 7435 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1

Представьте, что итератор для какого-то контейнера на самом деле
является обычным указателем. Но для алгоритмов из STL нужно больше
сведений, чем этот указатель может предоставить, а поместить «внутрь»
него соответствующие typedef-ы нельзя. Вот для этого, в частности, и
нужны traits.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *