Почему алгоритмы диапазонов несовместимы с итераторами std?

#include <vector>
#include <iostream>
#include <range/v3/all.hpp>

int main()
{
    auto coll = std::vector{ 1, 2, 3 };

    ranges::copy(
        coll,
        ranges::ostream_iterator<int>{  std::cout, ", " }
    ); // ok

    ranges::copy(
        coll, 
        std::ostream_iterator<int>{ std::cout, ", " }
    ); // error 
}

Проблема показана в приведенном выше коде. Я использую range-v3-0.3.7.

Для меня общий алгоритм copy не должен заботиться о типе итератора назначения, если он соответствует требованиям итератора вывода.

Если да, то почему алгоритмы диапазонов несовместимы с итераторами std?


person xmllmx    schedule 21.09.2018    source источник
comment
В основном потому, что поддержка диапазонов является экспериментальной и еще не стандартной, поэтому std::ostream_iterator разработан без какой-либо поддержки диапазонов. Дело в том, чтобы продемонстрировать возможность формального введения такой поддержки в будущий стандарт, а не ограничивать полную спецификацию. Предположительно, если диапазоны будут введены в будущую версию стандарта, спецификация для ranges::ostream_iterator станет частью спецификации для std::ostream_iterator, и ranges::copy() станет частью спецификации std::copy(), и любые несовместимости будут устранены.   -  person Peter    schedule 21.09.2018
comment
Ответ Петра не совсем точен. Было преднамеренно, что ranges::copy требует, чтобы его итератор вывода был конструктивным по умолчанию. И ranges::copy останется ranges::copy (std::ranges::copy, если быть точным) и не будет объединен с std::copy. См. Ответ Барри ниже.   -  person Eric Niebler    schedule 21.09.2018
comment
@EricNiebler: Нужно ли ranges::copy создавать итератор вывода по умолчанию? (Почему?) Если нет, то это кажется ненужной несовместимостью ...   -  person Nemo    schedule 27.06.2019
comment
Вы пробовали использовать C ++ 20, en.cppreference.com/w/cpp / iterator / ostream_iterator / говорит, что std::ostream_iterator является конструктивным по умолчанию, что означает из обсуждений, что он будет работать.   -  person alfC    schedule 07.06.2021
comment
@Nemo, у меня такое чувство, что диапазоны всегда требуют большего, чем то, что им нужно. Я также спрашиваю себя, зачем копированию нужна конструкция итератора по умолчанию? Может быть, это означает, что я неправильно думаю о проблеме. Возможно, это общее требование, чтобы итераторы были правильными типами значений, в частности, конструктивными по умолчанию. Но всегда кажется, что за любым конкретным алгоритмом скрывается более слабая концепция. Однажды я провел эмпирический обзор алгоритмов, которые синтаксически нуждались в построении по умолчанию: я смог найти только 2 в STL, и они кажутся бесплатными в реализации   -  person alfC    schedule 07.06.2021


Ответы (1)


Для меня общий алгоритм copy не должен заботиться о типе итератора назначения, если он соответствует требованиям итератора вывода.

Это правильно. Дело не в том, что ranges::copy каким-то образом распознает ranges::ostream_iterator, а не std::ostream_iterator. Дело в том, что Ranges имеет усовершенствованную концепцию того, что такое OutputIterator , так что ranges::ostream_iterator моделирует OutputIterator, а std::ostream_iterator - нет.

В частности, _7 _ требуется _8 _, который уточняет _9 _ для чего требуется DefaultConstructible. std::ostream_iterator - нет.

Отсюда неудача.


В P0896 диапазон- Алгоритм на основе copy() действительно требует WeaklyIncrementable (и, следовательно, DefaultConstructible) для своего итератора вывода, но устраняет это несоответствие, также добавляя конструктор по умолчанию к std::ostream_iterator (см. стр. 70).


В качестве обновления к этому P2325R3 был принят задним числом для C ++ 20, который отменяет это изменение. std::ostream_iterator больше не будет конструктивным по умолчанию, и концепция weakly_incrementable больше не будет требовать конструктивности по умолчанию (среди других изменений).


Обратите внимание, что концепция OutputIterator range-v3 / Ranges TS / Ranges Proposal отличается от существующей концепции OutputIterator в стандартной библиотеке. std::ostream_iterator не моделирует первое, но моделирует второе, поэтому использование std::copy с std::ostream_iterator сегодня совершенно нормально. И после P0896, использование ranges::copy с std::ostream_iterator тоже подойдет - из-за предложенных изменений в std::ostream_iterator.

person Barry    schedule 21.09.2018
comment
Да, намного лучше и гораздо менее страшно :) - person Yakk - Adam Nevraumont; 26.09.2018
comment
Хм ... почему ranges::ostream_iterator может быть сконструирован по умолчанию? Разве для этого не нужен поток? - person einpoklum; 10.05.2019
comment
@einpoklum В этом нет необходимости - вы всегда можете назначить его позже. - person Barry; 10.05.2019
comment
@Barry: Я думал, что в наши дни отделение официального строительства от эффективного строительства было чем-то вроде запрета. Вы вообще можете что-нибудь сделать с ranges::ostream_iterator {}? - person einpoklum; 10.05.2019
comment
@einpoklum Нет, на самом деле ты не можешь. - person Barry; 11.05.2019
comment
@Barry: Странно; Я только что спросил об этом в отдельном вопросе. - person einpoklum; 11.05.2019
comment
@einpoklum, std::ostream_iterator конструктивно по умолчанию в C ++ 20, en.cppreference.com / w / cpp / iterator / ostream_iterator /. - person alfC; 07.06.2021
comment
@alfC На сегодняшний день нет. - person Barry; 07.06.2021