Для меня общий алгоритм copy
не должен заботиться о типе целевого итератора, если он удовлетворяет требованиям выходного итератора.
Это правильно.Дело не в том, что ranges::copy
как-то распознает ranges::ostream_iterator
, а не std::ostream_iterator
.Дело в том, что у Ranges есть усовершенствованная концепция того, что такое OutputIterator † , такой, что ranges::ostream_iterator
моделирует OutputIterator, но std::ostream_iterator
не .
В частности, ranges::copy()
требует WeaklyIncrementable<O>
, что уточняет SemiRegular<O>
, которое требует DefaultConstructible
.ranges::ostream_iterator
является конструируемым по умолчанию, но std::ostream_iterator
- нет.
Отсюда и ошибка.
В P0896 алгоритм copy()
на основе диапазона требует WeaklyIncrementable
(и, следовательно, DefaultConstructible
) для своего выходного итератора - но устраняет это несоответствие, также добавляя конструктор по умолчанию к std::ostream_iterator
(см. стр. 70).
† Обратите внимание, что концепция range-v3 / Ranges TS / Ranges Proposal OutputIterator отделена от существующей концепции OutputIterator стандартной библиотеки.std::ostream_iterator
не моделирует первое, но моделирует второе - так что использование std::copy
с std::ostream_iterator
сегодня прекрасно.И после P0896, использование ranges::copy
с std::ostream_iterator
также будет хорошо - из-за предложенных изменений в std::ostream_iterator
.