Это довольно хорошо, за исключением того, что компилятор ничего не понимает. Это не похоже на оптимизацию компилятора или что-то еще. Какая реализация используется, руководствуется разработчиком и его применением правил языка C ++.

ытался понять реализацию итератора, и, играя с источником, я увидел это утверждение:

typedef output_iterator_tag iterator_category;

Я не понимаю, как этот typedef работает в классе? Какой побочный эффект это дает? Кто-нибудь может провести меня через это?

Ответы на вопрос(2)

Решение Вопроса

потому что вы вряд ли получите этот ответ.

«Выходной итератор» - это концепция, которой соответствуют определенные итераторы. Каждый итератор, который является реализацией этой концепции, имеет определенные функциональные возможности, связанные с ним. Это как наследство, но это не так.

C ++ не имеет ничего такого, что представляло бы концепции (было предложено дополнение к C ++ 0x, но не смогло сделать это). В этом случае нам нужны различные конструкции шаблона, чтобы позволить нам связать «тег» с типом итератора. Связывая тип output_iterator_tag с итератором, мы утверждаем, что наш тип итератора реализует концепцию OutputIterator.

Это становится очень важным, когда вы пытаетесь написать алгоритмы, которые максимально оптимизированы, а также являются общими. Например, выполнение сортировки с помощью итератора, который может быть увеличен или уменьшен на произвольное значение (иными словами, чем 1), более эффективно, чем то, которое не имеет такой возможности. Кроме того, чтобы получить новый итератор, который находится на расстоянии X от другого, могут потребоваться различные операции в зависимости от возможностей итератора. Для написания такого алгоритма вы используете «диспетчеризацию тегов». Чтобы объяснить это более полно, вот реализация (непроверенная) std :: advance, которая работает как с итераторами, которые имеют оператор + =, так и с итераторами, которые имеют только оператор ++, и работает максимально быстро с обеими версиями.

template < typename RandomAccessIterator >
RandomAccessIterator advance( RandomAccessIterator it
                            , int amount
                            , random_access_iterator_tag) 
{ return it + amount; }

template < typename ForwardIterator >
ForwardIterator advance(ForwardIterator it, int amount, forward_iterator_tag)
{
  for (;amount; --amount) ++it;
  return it;
}

template < typename Iterator >
Iterator advance(Iterator it, int amount)
{
  typedef typename std::iterator_traits<Iterator>::iterator_tag tag;
  advance(it, amount, tag());
}

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

Опять же, читайте об общем программировании. Это важно для использования всех возможностей C ++.

Да, и наконец ... typedef есть в определении класса итератора, потому что это удобное и удобное место для его размещения. Итератор по умолчанию итератор может искать его там. Вы захотите использовать iterator_traits, а не это определение, потому что необработанные указатели тоже являются итераторами и не могут иметь внутренних typedefs.

 Chan14 янв. 2011 г., 07:12
Робертс: Мне нравится, как ты читал лекции;)! Большое спасибо ;)
 templatetypedef14 янв. 2011 г., 06:33
+1 Красивый ответ!
 GManNickG03 апр. 2018 г., 06:36
Было ли время, когда черта typedef была названаiterator_tag? Кажется, это на самом деле должно бытьiterator_category, (тоже привет!)

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

Например, в заголовке VS2010 алгоритм "std :: distance" имеет две реализации в зависимости от typedef'd типа iterator_category в переданных итераторах.

Для вычисления расстояния между двумя итераторами std :: distance требуется только входной итератор, но для вычисления ответа может потребоваться линейное время 'O (n)'.

Если, однако, компилятор выяснит, что используется итератор произвольного доступа, и тем самым может воспользоваться оператором вычитания для вычисления расстояния за постоянное время 'O (1)'.

Я бы порекомендовал смотреть Стефана Т. Лававеявидео где он идет немного в черты типа и их использование в стандартной библиотеке шаблонов.

 Crazy Eddie14 янв. 2011 г., 06:43
Это довольно хорошо, за исключением того, что компилятор ничего не понимает. Это не похоже на оптимизацию компилятора или что-то еще. Какая реализация используется, руководствуется разработчиком и его применением правил языка C ++.

Ваш ответ на вопрос