![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Improved Iterator Categories and RequirementsBoost , ,
|
Document number: |
J16/01-0011 = WG21 N1297 |
Date: |
21 марта 2001 года |
Author: |
Джереми Сик, |
Производитель Iterator | *i = a |
Итератор ввода | *iконвертируется вT |
Передний итератор | *i-T&(илиconst T&после решениявопроса 200 |
Итератор случайного доступа | i[n]конвертируется вT(что странно, потому что операционная семантика говоритi [n]эквивалентна* (i + n), который будет иметь тип возврата). T& |
Из-за смешивания итератора и типа возврата отсчета многие полезные итераторы не могут быть соответствующим образом классифицированы. Например,vector
Другой пример — итератор подсчета, итератор возвращает последовательность целых чисел при инкрементировании и отсчете (см.boost::counting_iterator). Существует два способа реализации этого итератора: 1) сделатьэталонныйтип истинной ссылкой (ссылка на целый элемент данных счетного итератора) или 2) сделатьэталонныйтип таким же, какзначение_тип. Вариант 1) сталкивается с проблемами, обсуждаемыми вВыпуске 198, ссылка не будет действительна после уничтожения итератора. Поэтому вариант 2) является лучшим выбором, но тогда у нас есть счетчик итератора, который не может быть итератором случайного доступа.
Еще одним примером является преобразующий итератор, адаптер итератора, который применяет объект унарной функции к сносному значению обернутого итератора (см.boost::transform_iterator). Для унарных функций, таких какstd::times, тип возврата оператора*явно должен бытьresult_typeобъекта функции, который обычно не является ссылкой. Однако при нынешних требованиях к итератору, если вы завернетеint*с преобразователем, вы получите не итератор случайного доступа, как ожидалось, а итератор ввода.
Четвертый пример можно найти в итераторах вершины и края библиотекиBoost Graph Library. Эти итераторы возвращают дескрипторы вершины и края, которые являются легкими ручками, созданными на лету. Они должны быть возвращены по стоимости. В результате их текущей стандартной категорией итераторов являетсяstd::input_iterator_tag, что означает, что, строго говоря, вы не можете использовать эти итераторы с такими алгоритмами, какstd::min_element().. В качестве временного решения мы представили концепциюMulti-Pass Input Iteratorдля описания дескрипторов вершины и края, но, как показывают примечания к концепции, требуется лучшее решение.
Короче говоря, есть много полезных итераторов, которые не вписываются в текущие стандартные категории итераторов. В результате происходят следующие плохие вещи:
Примечание: мы рассмотрели определение одноместного итератора, который может быть объединен с читаемым или письменным итератором для замены требований к вводу и выводу итератора. Мы отвергли эту идею, потому что существует несколько различий между итераторами ввода и вывода, которые затрудняют их объединение: итератор ввода требует сопоставимого равенства, а итератор вывода - нет, а итератор ввода требует назначения, а итератор вывода - нет.
namespace std { // Return Type Categories struct readable_iterator_tag { }; struct writable_iterator_tag { }; struct swappable_iterator_tag { }; struct mutable_lvalue_iterator_tag : virtual public writable_iterator_tag, virtual public readable_iterator_tag { }; struct constant_lvalue_iterator_tag : public readable_iterator_tag { }; // Traversal Categories struct forward_traversal_tag { }; struct bidirectional_traversal_tag : public forward_traversal_tag { }; struct random_access_traversal_tag : public bidirectional_traversal_tag { }; }And there will need to be a way to access these category tags using a traits mechanism. Adding new typedefs to std::iterator_traits is not an acceptable solution because that would break every existing iterator. Instead, we propose two new traits classes. It is important that these traits classes are backward compatible, that is, they should work with any iterator for which there is a valid definition of std::iterator_traits. This can be accomplished by making the default behavior of the traits classes map the iterator_category of the iterator to the appropriate return or traversal category. For new iterators, either specializations of these traits classes can be defined, or the iterator can provide nested typedefs, and inherit from new_iterator_base (which is just a signal to the traits class that it is a new iterator). As with std::iterator_traits, specializations for T* are provided.
namespace std { struct new_iterator_base { }; template <typename Iterator> struct return_category { // Pseudo-code if (Iterator inherits from new_iterator_base) { typedef typename Iterator::return_category type; } else { typedef std::iterator_traits<Iterator> OldTraits; typedef typename OldTraits::iterator_category Cat; if (Cat inherits from std::forward_iterator_tag) if (is-const(T)) typedef boost::constant_lvalue_iterator_tag type; else typedef boost::mutable_lvalue_iterator_tag type; else if (Cat inherits from std::input_iterator_tag) typedef boost::readable_iterator_tag type; else if (Cat inherits from std::output_iterator_tag) typedef boost::writable_iterator_tag type; } }; template <typename T> struct return_category<T*> { // Pseudo-code if (is-const(T)) typedef boost::constant_lvalue_iterator_tag type; else typedef boost::mutable_lvalue_iterator_tag type; }; template <typename Iterator> struct traversal_category { // Pseudo-code if (Iterator inherits from new_iterator_base) { typedef typename Iterator::traversal_category type; } else { typedef std::iterator_traits<Iterator> OldTraits; typedef typename OldTraits::iterator_category Cat; if (Cat inherits from std::random_access_iterator_tag) typedef boost::random_access_traversal_tag type; else if (Cat inherits from std::bidirectional_iterator_tag) typedef boost::bidirectional_traversal_tag type; else if (Cat inherits from std::forward_iterator_tag) typedef boost::forward_traversal_tag type; } }; template <typename T> struct traversal_category<T*> { typedef boost::random_access_traversal_tag type; }; }
Algorithm | Requirement Change |
---|---|
find_end | Передний итератор -> Forward Traversal Iterator and Readable Iterator |
Find_first_of | |
Обсуждение Next_find | |
поиск | |
Search_n | |
ротация_копия | |
Нижний ->> | |
верхний | |
равный | |
binary_search | |
мин_элемент | |
max_element | |
iter_swap | Передний итератор -> Swappable Iterator |
заполнять | Передний итератор -> Forward Traversal Iterator and Writable Iterator |
генерировать | |
swap_ranges | Передний итератор -> Forward Traversal Iterator and Swappable Iterator |
вращать | |
заменить | Передний итератор -> Forward Traversal Iterator and Readable Iterator and Writable Iterator |
Заменить | |
удалять | |
Удалить ___ | |
уникальный | |
обратный | Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator |
раздел | |
copy_backwards | Двунаправленный итератор ->Двунаправленный итератор поворота и читаемый итератор Двунаправленный итератор ->Двунаправленный итератор поворота и письменный итератор |
Next_Пермутация | Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator |
prev_permutation | |
Стабильный_раздел | Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator |
Вместо_merge | |
reverse_copy | Двунаправленный итератор ->Двунаправленный итератор поворота и читаемый итератор |
random_suffle | Итератор случайного доступа -> Random Access Traversal Iterator and Swappable Iterator |
сортировать | |
stable_sort | |
part_sort | |
nth_элемент | |
push_ap | |
pop_ap | |
make_ap | |
сорт |
X | Тип итератора. |
Т | Тип значенияX, т.е.std::iterator_traits |
x,y | Объект типаX. |
t | Объект типаТ. |
Тип значения | std::iterator_traits |
Тип объектов, на которые указывает итератор. |
Тип ссылки | std::iterator_traits |
Тип возврата отсылки к итератору. Этот тип должен быть конвертируемым вТ. |
Возвратная категория | std::return_category |
Тип конвертируемого вstd::readable_iterator_tag |
Name | Expression | Type requirements | Return type |
---|---|---|---|
Уважение | *x | std::iterator_traits | |
Доступ к члену | x->m | Tпредставляет собой тип с элементом, названнымm. | Еслиmявляется членом данных, то типm. Еслиmявляется функцией члена, то возвращаемый типm. |
Возвратная категория | std::return_category |
Тип конвертируемого вstd::writable_iterator_tag |
Name | Expression | Return type |
---|---|---|
Уважение | *x = a | неуточненный |
Примечание: требования к Swappable Iterator зависят от проблем, связанных с решениемstd::swap(). Здесь мы предполагаем, что проблема будет решена, разрешив перегрузкуstd::swap()для определенных пользователем типов.
Примечание: Readable Iterator and Writable Iterator Combined подразумевает Swappable Iterator из-за полностью шаблонизированногоstd::swap(). Однако Swappable Iterator не подразумевает ни Readable Iterator, ни Writable Iterator.
Возвратная категория | std::return_category |
Тип конвертируемого вstd::swappable_iterator_tag |
Name | Expression | Return type |
---|---|---|
Iterator Swap | std::iter_swap(x, y) | void |
Dereference and Swap | std::swap(*x, *y) | void |
Тип ссылки | std::iterator_traits |
Тип возврата отсылки итератора, который должен бытьconst T&. | std::iterator_traits |
Указатель на тип значения, который должен бытьconst T*. | -->
Возвратная категория | std::return_category |
Тип конвертируемого вstd::constant_lvalue_iterator_tag |
Тип ссылки | std::iterator_traits |
Тип возврата отсылки итератора, который должен бытьT&. | std::iterator_traits |
Указатель на тип значения, который являетсяT*. | -->
Возвратная категория | std::return_category |
Тип конвертируемого вstd::mutable_lvalue_iterator_tag |
Разностный тип | std::iterator_traits |
Знаковый интегральный тип, используемый для представления расстояний между итераторами, которые указывают на один и тот же диапазон. |
Траверсная категория | std::traversal_category |
Тип конвертируемого вstd::forward_traversal_tag |
Name | Expression | Type requirements | Return type |
---|---|---|---|
Прирост | ++i | X& | |
Постприрост | i++ | конвертируемый вconst X& |
Траверсная категория | std::traversal_category |
Тип конвертируемого вstd::bidirectional_traversal_tag |
Name | Expression | Type requirements | Return type |
---|---|---|---|
Предварительное определение | --i | X& | |
Постдекрет | Я-- | конвертируемый вconst X& |
Траверсная категория | std::traversal_category |
Тип конвертируемого вstd::random_access_traversal_tag |
Name | Expression | Type requirements | Return type |
---|---|---|---|
Добавление итератора | i += n | X& | |
Добавление итератора | i + nилиn + i | X | |
Вычитание итератора | i -= n | X& | |
Вычитание итератора | i - n | X | |
Разница | i - j | std::iterator_traits | |
Оператор элемента | i [n] | Xтакже должна быть моделью. Читаемый итератор. | std::iterator_traits |
Задание элементов | i [n] = t | Xтакже должна быть моделью. Итератор. | неуточненный |
Статья Improved Iterator Categories and Requirements раздела может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: ::
реклама |