В C ++ 17 нет такой вещи, как std::contiguous_iterator
. Однако существует ContiguousIterator с именем требование . Это представляет итератор произвольного доступа для последовательности элементов, где каждый элемент хранится непрерывно, точно так же, как массив. Это означает, что при наличии указателя на value_type
от итератора возможно выполнить арифметику указателя c для этого указателя, которая должна работать точно так же, как и выполнение той же арифметики c на соответствующих итераторах .
Цель этого состоит в том, чтобы обеспечить более эффективную реализацию алгоритмов на смежных итераторах. Или запретить использование алгоритмов на несмежных итераторах. Один из примеров того, где это имеет значение, - это если вы пытаетесь передать итераторы C ++ в интерфейс C, основанный на указателях на массивы. Вы можете обернуть такие интерфейсы за общие c алгоритмы, проверяя смежность итератора в шаблоне.
Или, по крайней мере, теоретически; в C ++ 17 это было на самом деле невозможно .. Причина в том, что на самом деле не было способа проверить, является ли итератор ContiguousIterator. Нет способа спросить указатель, если выполнение арифметики указателя c для указателя на элемент из итератора допустимо. И не было std::contiguous_iterator_category
, которое можно было бы использовать для таких итераторов (поскольку это могло вызвать проблемы совместимости). Таким образом, вы не можете использовать инструменты SFINAE для проверки непрерывности итератора.
C ++ 20 std::contiguous_iterator
концепция решает эту проблему. Это также решает другую проблему с непрерывными итераторами. Смотрите, приведенное выше объяснение поведения ContiguousIterator начинается с того, что у нас есть указатель на элемент из диапазона. Ну, как ты это получил? Очевидным способом было бы сделать что-то вроде std::addressof(*it)
, но что если it
является конечным итератором? Конечный итератор не поддерживает разыменование, поэтому вы не можете этого сделать. В принципе, даже если вы знаете, что итератор является смежным, как вы go конвертируете его в эквивалентный указатель?
Концепция std::contiguous_iterator
решает обе эти проблемы. std::to_address
доступно, что преобразует любой непрерывный итератор в эквивалентное значение указателя. И есть тег traits, который итератор должен предоставить, чтобы обозначить, что он на самом деле является смежным итератором, просто в этом случае реализация по умолчанию to_address
оказывается действительной для несмежного итератора.