Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

New Iterator Concepts

Boost , ,

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

New Iterator Concepts

Author: Дэвид Абрахамс, Джереми Сик, Томас Витт
Contact: Авторские права Дэвид Абрахамс, Джереми Сик и Томас Витт 2003.
Abstract:We propose a new system of iterator concepts that treat access and positioning independently. This allows the concepts to more closely match the requirements of algorithms and provides better categorizations of iterators that are used in practice.

Motivation

Стандартные категории и требования итератора имеют недостатки, поскольку они используют одну иерархию понятий для решения двух ортогональных вопросов: прохождение итератора и доступ к значению . В результате многие алгоритмы с требованиями, выраженными в категориях итераторов, слишком строги. Кроме того, многие реальные итераторы не могут быть точно классифицированы. Например, прокси-итератор со случайным доступом может юридически иметь только категорию "входной итератор", поэтому общие алгоритмы не могут воспользоваться его возможностями случайного доступа. Нынешняя иерархия концепции итератора ориентирована на обход итератора (отсюда названия категорий), в то время как требования, касающиеся доступа к стоимости, проникают в различные места. В следующей таблице приводится краткое изложение текущих требований к доступу к стоимости в категориях итераторов.

Value Access Requirements in Existing Iterator Categories
Производитель Iterator *i = a
Итератор ввода *i можно конвертировать в T
Передний итератор *i T& (или const T& после разрешения выпуска 200)
Итератор случайного доступа i[n] преобразуется в T (также i[n]=t требуется для итераторов с изменяемостью после разрешения вопрос 299)

Поскольку обход итератора и доступ к стоимости смешиваются в одной иерархии, многие полезные итераторы не могут быть соответствующим образом классифицированы. Например, vector::iterator является почти итератором случайного доступа, но тип возврата не bool& (см. выпуск 96 и статья Херба Саттера J16/99-0008 = WG21 N1185). Поэтому итераторы вектор отвечают только требованиям входного итератора и выходного итератора. Это настолько нелогично, что стандарт C++ противоречит самому себе. В пункте 23.2.4/1 говорится, что вектор является последовательностью, которая поддерживает итераторы случайного доступа.

Другим сложным для категоризации итератором является преобразующий итератор, адаптер, который применяет объект унарной функции к отнесенному значению некоторого базового итератора (см. transform_iterator). Для унарных функций, таких как times, тип возврата оператора* явно должен быть result_type объекта функции, который обычно не является ссылкой. Поскольку итераторы случайного доступа должны возвращать значения l от оператора*, если вы обернете int* с помощью итератора преобразования, вы получите итератор случайного доступа не так, как можно было бы ожидать, а итератор ввода.

Третий пример можно найти в итераторах вершины и края библиотеки Boost Graph Library. Эти итераторы возвращают дескрипторы вершины и края, которые являются легкими ручками, созданными на лету. Они должны быть возвращены по стоимости. В результате их текущая стандартная категория итераторов - input_iterator_tag, что означает, что, строго говоря, вы не можете использовать эти итераторы с такими алгоритмами, как min_element(). В качестве временного решения была введена концепция Multi-Pass Input Iterator для описания дескрипторов вершины и края, но, как показывают примечания к концепции, требуется лучшее решение.

Короче говоря, есть много полезных итераторов, которые не вписываются в текущие стандартные категории итераторов. В результате происходят следующие плохие вещи:

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

Impact on the Standard

Это предложение для TR1 является чистым расширением. Кроме того, новые концепции итератора обратно совместимы со старыми требованиями итератора, а старые итераторы - с новыми концепциями итератора. Другими словами, итераторы, удовлетворяющие старым требованиям, также удовлетворяют соответствующим концепциям в новой системе, и итераторы, моделирующие новые концепции, автоматически удовлетворяют соответствующим старым требованиям.

Possible (but not proposed) Changes to the Working Paper

Расширения в этом документе предлагают несколько изменений, которые мы можем внести в рабочий документ для следующего стандарта. Эти изменения не являются формальной частью этого предложения по TR1.

Changes to Algorithm Requirements

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

Для следующего рабочего документа (но не для TR1) комитет должен рассмотреть следующие изменения в требованиях к типу алгоритмов. Эти изменения сформулированы как текстовые замены, перечисляя алгоритмы, к которым применяется каждая текстовая замена.

Передний итератор (Forward Traversal Iterator and Readable Iterator)

find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element

Передний итератор (1) -> Single Pass Iterator и Readable Iterator, Forward Iterator (2) -> Forward Traversal Iterator и Readable Iterator

find_first_of

Передний итератор - > читаемый итератор и письменный итератор

iter_swap

Forward Iterator - > Итератор с одним проходом и письменный итератор

fill, generate

Форвардный итератор (Forward Traversal Iterator and Swappable Iterator)

rotate

Передний итератор (1) -> Swappable Iterator и Single Pass Iterator, Forward Iterator (2) -> Swappable Iterator и Incrementable Iterator

swap_ranges
Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator
remove, remove_if, unique

Forward Iterator -> Single Pass Iterator и Readable Iterator

replace, replace_if
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator
reverse
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator
partition

Двунаправленный итератор (1) -> двунаправленный итератор поворота и читаемый итератор, двунаправленный итератор (2) -> двунаправленный итератор поворота и письменный итератор

copy_backwards
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator
next_permutation, prev_permutation
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator
stable_partition, inplace_merge
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator
reverse_copy
Random Access Iterator -> Random Access Traversal Iterator and Readable and Writable Iterator
random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap make_heap, sort_heap
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
equal, mismatch
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
transform

Deprecations

Для следующего рабочего документа (но не для TR1) комитету следует рассмотреть возможность обесценивания старых тегов итератора и std::iterator_traits, поскольку он будет заменен отдельными метафункциями признаков.

vector<bool>

Для следующего рабочего документа (но не для TR1) комитету следует рассмотреть возможность реклассификации vector::iterator в качестве итератора случайного доступа и итератора для чтения и итератора для записи.

Design

Требования к итератору должны быть разделены на две группы. Один набор понятий обрабатывает синтаксис и семантику доступа к стоимости:

  • Читаемый итератор
  • Письменный итератор
  • Заменяемый итератор
  • Lvalue итератор

Концепции доступа описывают требования, относящиеся к оператору* и оператору->, включая значение_тип, ссылка и поисковик ассоциированных типов.

Другой набор понятий обрабатывает прохождение:

  • Необычный итератор
  • Итератор Single Pass
  • Вперед Traversal Iterator
  • Двунаправленный итератор поворотов
  • Случайный доступ Traversal Iterator

Соотношения уточнения для концепций прохождения находятся на следующей диаграмме.

traversal.png

В дополнение к операторам движения итератора, таким как оператор++, концепции обхода также включают требования к сравнению позиций, такие как оператор== и оператор<. Причина тонкого срезания концептов в Инкрементируемый и Единый проход состоит в том, чтобы предоставить концепции, которые точно соответствуют первоначальным требованиям итератора ввода и вывода.

Это предложение также включает в себя концепцию для определения, когда итератор совместим с другим итератором, в том смысле, что int* совместим с intconst*.

  • Взаимодействующие итераторы

Связь между понятиями нового итератора и старого приведена на следующей диаграмме.

oldeqnew.png

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

Наш дизайн повторно использует iterator_traits::iterator_category, чтобы указать возможность прохождения итератора. Чтобы указать возможности, не захваченные какой-либо категорией итератора старого стиля, дизайнер итератора может использовать тип iterator_category, который конвертируется как в наиболее производный старый тег категории итератора, который подходит, так и в соответствующий новый тег обхода итератора.

Мы не предоставляем теги для отправки на основе концепций доступа, отчасти потому, что мы не смогли найти способ автоматически вывести правильные теги доступа для итераторов старого стиля. Письменность итератора может зависеть от возможности присваивания его value_type и нет известного способа определить, можно ли назначить произвольный тип. К счастью, потребность в диспетчеризации на основе возможностей доступа не так велика, как потребность в диспетчеризации на основе возможностей прохождения.

Сложное дизайнерское решение касалось оператора . Прямой подход для определения оператор [] будет иметь тип возврата ссылка ; такой же, как оператор*. Однако движение в этом направлении будет означать, что итератор, удовлетворяющий старым требованиям Random Access Iterator, не обязательно будет моделью Readable или Writable Lvalue Iterator. Вместо этого мы выбрали дизайн, который соответствует предпочтительному разрешению , выпуск 299: оператор [] требуется только для возврата чего-либо конвертируемого в value_type (для Readable Iterator), и требуется поддержка назначения i[n] t (для Writable Iterator).

Proposed Text

Addition to [lib.iterator.requirements]

Iterator Value Access Concepts [lib.iterator.value.access]

В таблицах ниже X является типом итератора, a является постоянным объектом типа R является std::iterator_traits::reference, T является std::iterator_traits::value_type и v является постоянным объектом типа T.

Readable Iterators [lib.readable.iterators]

Класс или встроенный тип X моделирует концепцию Readable Iterator для типа значения T, если, помимо того, что X является Подлежащим и Копируемым, следующие выражения являются действительными и уважают заявленную семантику. U - тип любого указанного элемента типа T.

Readable Iterator Requirements (in addition to Assignable and Copy Constructible)
Expression Return Type Note/Precondition
iterator_traits::value_type T Любой нессылочный, не-cv-квалифицированный тип
*a Преобразуется в T
pre: a является уважительным. Если a ==b, то *a
эквивалентно *b.
a>m U& pre: pre: (*a.m четко определен. Эквивалент (*a.m.

Writable Iterators [lib.writable.iterators]

Класс или встроенный тип X моделирует концепцию Письменный итератор, если в дополнение к X Конструктивные, следующие выражения действительны и уважают заявленную семантику. Записываемые итераторы имеют ассоциированный набор типов значений .

Writable Iterator Requirements (in addition to Copy Constructible)
Expression Return Type Precondition
*a=o   pre: Тип o находится в наборе типов значений X

Swappable Iterators [lib.swappable.iterators]

Класс или встроенный тип X моделирует концепцию Swappable Iterator, если в дополнение к X Конструктивные, следующие выражения действительны и уважают заявленную семантику.

Swappable Iterator Requirements (in addition to Copy Constructible)
Expression Return Type Postcondition
iter_swap(a, b) void указанные значения обмениваются

[Примечание: Итератор, являющийся моделью концепций Readable Iterator и Writable Iterator, также является моделью Swappable Iterator. - конец примечания

Lvalue Iterators [lib.lvalue.iterators]

Концепция Lvalue Iterator добавляет требование, чтобы тип возврата operator* был ссылкой на тип значения итератора.

Lvalue Iterator Requirements
Expression Return Type Note/Assertion
*a T& T - cv iterator_traits::value_type, где cv - необязательная квалификация cv. a является уважительным.

Если X является Письменный итератор, то a==b если и только если *a является тем же объектом, что и *b. Если X является Readable Iterator, то a==b подразумевает *a тот же объект, что и *b.

Iterator Traversal Concepts [lib.iterator.traversal]

В приведенных ниже таблицах X является типом итератора, a являются постоянными объектами типа X, r и s являются изменчивыми объектами типа X, T является std::iterator_traits::value_type и v является постоянным объектом типа T.

Incrementable Iterators [lib.incrementable.iterators]

Класс или встроенный тип X моделирует концепцию Incrementable Iterator, если, помимо того, что X является приемлемым и конструируемым для копирования, следующие выражения являются действительными и уважают заявленную семантику.

Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible)
Expression Return Type Assertion
++r X& &r == &++r
r++    
*r++    
iterator_traversal::type<3 Преобразуемый в incrementable_traversal_tag  

Если X является Письменный итератор, то X a(r++); эквивалентен X ++r;r++oo;++r. Если X является Readable Iterator, то T z(*r++); эквивалентно T z(*r); ++r;.

Single Pass Iterators [lib.single.pass.iterators]

Класс или встроенный тип X моделирует концепцию Single Pass Iterator, если следующие выражения действительны и уважают заявленную семантику.

Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable)
Expression Return Type Operational Semantics Assertion/ Pre-/Post-condition
++r X&   pre: r является сносным; post: r является сносным или r является прошедшим-концом
a==b конвертируемый в bool   == является отношением эквивалентности по своей области
a!=b конвертируемый в bool !(a == b)  
iterator_traits::difference_type Знаковый интегральный тип, представляющий расстояние между итераторами    
iterator_traversal::type<3 Преобразуемый в single_pass_traversal_tag    

Forward Traversal Iterators [lib.forward.traversal.iterators]

Класс или встроенный тип X моделирует концепцию Forward Traversal Iterator, если, помимо X, удовлетворяет требованиям Default Constructible и Single Pass Iterator, следующие выражения действительны и уважают заявленную семантику.

Forward Traversal Iterator Requirements (in addition to Default Constructible and Single Pass Iterator)
Expression Return Type Assertion/Note
Xu; X& примечание: u может иметь единственное значение.
++r X& r == и r является допустимым ++r == ++s.
iterator_traversal::type<3 Преобразуемый в forward_traversal_tag  

Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]

Класс или встроенный тип X моделирует концепцию Bidirectional Traversal Iterator, если в дополнение к X удовлетворяют требованиям Forward Traversal Iterator, следующие выражения являются действительными и уважают заявленную семантику.

Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator)
Expression Return Type Operational Semantics Assertion/ Pre-/Post-condition
-r X&  

предыдущее: существует s так, что r == ++s. пост: s является сносным.

++(--r) == r. -r == -s подразумевает r ==. &r == &-r.

r-- конвертируемый в const X&
 { X tmp = r; -r; возврат tmp; } 
 
iterator_traversal::type<3 Преобразуемый в bidirectional_traversal_tag    

Random Access Traversal Iterators [lib.random.access.traversal.iterators]

Класс или встроенный тип X моделирует концепцию Random Access Traversal Iterator, если следующие выражения действительны и уважают заявленную семантику. В таблице ниже Distance является iterator_traits::difference_type и n представляет собой постоянный объект типа Distance.

Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator)
Expression Return Type Operational Semantics Assertion/ Precondition
r += n X&
 { Расстояние m = n; если (m >= 0) в то время как (m--) ++r; в то время как (m++) -r; возврат r; } 
 
an, n X { tmp = a; возврат tmp n; <21  
r -= n X& возврат r += -n  
a-n X { tmp = a; возврат tmp n;  
b-a Расстояние ab? distance(a,b):-distance(b,a) pre: существует значение n Расстояние, такое, что a + n ==b. b==a+(b-a).
a[n] конвертируемый в T *(a + n) pre: a - Readable Iterator
a[n]=v конвертируемый в T *(a + n) = v pre: a - Письменный итератор
a<b конвертируемый в bool b-a>0<11 < является отношением полного упорядочения
a > b конвертируемый в bool b<a > является отношением полного упорядочения
a >= b конвертируемый в bool !(a < b)  
a<=b конвертируемый в bool !(a > b)  
iterator_traversal::type<3 Преобразуемый в random_access_traversal_tag    

Interoperable Iterators [lib.interoperable.iterators]

Класс или встроенный тип X Single Pass Iterator совместим с классом или встроенным типом Y, который также моделируется Итератор с одним проходом, если следующие выражения действительны и уважают заявленную семантику. В таблицах ниже x является объектом типа X, y является объектом типа Y, Distance является iterator_traits::difference_type, а n представляет собой постоянный объект типа Distance.

Expression Return Type Assertion/Precondition/Postcondition
y = x Y y == x
Y(x) Y post: Y(x) == x
x ==y конвертируемый в bool == является отношением эквивалентности по своей области.
y == x конвертируемый в bool == является отношением эквивалентности по своей области.
x!=y конвертируемый в bool bool(a==b) != bool(a!=b) над его доменом.
y != x конвертируемый в bool bool(a==b) != bool(a!=b) над его доменом.

Если X и Y обе модели Random Access Traversal Iterator, то необходимо выполнить следующие дополнительные требования.

Expression Return Type Operational Semantics Assertion/ Precondition
x<y конвертируемый в bool y - x > 0<11 < является отношением полного упорядочения
y < x конвертируемый в bool x-y>0<11 < является отношением полного упорядочения
x > y конвертируемый в bool y < x > является отношением полного упорядочения
y > x конвертируемый в bool x<y > является отношением полного упорядочения
x >= y конвертируемый в bool !(x < y>2>  
y >= x конвертируемый в bool !(y < x)  
x <=y конвертируемый в bool !(x > y>2>  
y <= x конвертируемый в bool !(y > x)  
y - x Расстояние расстояние(Y(x),y) pre: существует значение n Расстояние, такое, что x + n ==y. y == x + (y-x).
x-y Расстояние расстояние(y,Y(x)) pre: существует значение n Расстояние, такое, что y + n == x. x==y+(x-y).

Addition to [lib.iterator.synopsis]

// lib.iterator.traits, traits and tags
template <class Iterator> struct is_readable_iterator;
template <class Iterator> struct iterator_traversal;
struct incrementable_traversal_tag { };
struct single_pass_traversal_tag : incrementable_traversal_tag { };
struct forward_traversal_tag : single_pass_traversal_tag { };
struct bidirectional_traversal_tag : forward_traversal_tag { };
struct random_access_traversal_tag : bidirectional_traversal_tag { };

Addition to [lib.iterator.traits]

Шаблон класса is_readable_iterator удовлетворяет требованиям UnaryTypeTrait.

Учитывая тип итератора X, is_readable_iterator::value дает true, если для объекта a типа X можно преобразовать iterator_traits::value_type и false в противном случае.

iterator_traversal::type<3 is

category-to-traversal(iterator_traits<X>::iterator_category)

где категория-переход определяется следующим образом:

category-to-traversal(C) =
    if (C is convertible to incrementable_traversal_tag)
        return C;
    else if (C is convertible to random_access_iterator_tag)
        return random_access_traversal_tag;
    else if (C is convertible to bidirectional_iterator_tag)
        return bidirectional_traversal_tag;
    else if (C is convertible to forward_iterator_tag)
        return forward_traversal_tag;
    else if (C is convertible to input_iterator_tag)
        return single_pass_traversal_tag;
    else if (C is convertible to output_iterator_tag)
        return incrementable_traversal_tag;
    else
        the program is ill-formed

Footnotes

Концепция UnaryTypeTrait определена в n1519; LWG рассматривает возможность добавления требования, что специализации получены из их вложенных ::type.

Статья New Iterator Concepts раздела может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-07-05 03:23:02/0.011393070220947/0