Как стать автором
Обновить

Комментарии 5

Если итератор двунаправленный или прямого доступа, то над терминатором должна быть определена операция декремента, возвращающая итератор.
Тогда можно спокойно переделать фасад функции sort — пусть она будет sort(Iterator start, Sentinel finish), а внутри творит что хочет.

Казалось бы, арифметика над терминатором ломает строгость:
begin() — итератор
end() — терминатор
end()-1 — итератор
end()-1+1 — итератор?!

На самом деле, строгость сломана изначально:
begin()+1 — итератор
begin()+distance(begin(),end()) — итератор == end().

Так что можно расслабиться. Мы в С++, а не в Агде, здесь супер-пупер-типизацией от всего не защитишься.
От самых примитивных косяков, тем не менее, защититься можно. Для этого интерфейсы STL-алгоритмов вполне могут быть sort(Iterator begin, Sentinel end).
Единственно, — поскольку такое объявление слишком расслабляет (можно подсунуть границы не только из разных доменов, но и из разных типов), — придётся ввести проверку

template<class S> using bool const is_sentinel = __unspecified__;
template<class I> using bool const is_iterator = is_sentinel<I> && __unspecified__;
template<class I, class S> using bool const is_iterator_and_sentinel = is_iterator<I> && is_sentinel<S> && __unspecified__;

которая показывает, относятся ли I и S к границам одного типа.
И, соответственно,
template<class I, class S>
auto sort(I, S) -> typename enable_if< is_iterator_and_sentinel<I,S>, void >::type;

Ну, автор оригинального текста решает всё-таки чуть более широкую задачу. Поэтому получается сложнее.
А можно в цикл статей добавить оглавление со ссылками на все части? Было бы удобней :)
Да, спасибо за замечание, сейчас добавлю.
Лучше в начало, но и так гораздо лучше, чем без них. Спасибо.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий