Судя по всему, в C++20 появилась новая конструкция, связанная с std::istream
: std::istream_view
. Страница cppreference на нем сейчас незавершена†. Итак, что такое «вид istream
» и для чего я могу его использовать?
† - Ok, technically it redirects to a page about std::basic_istream_view
and that one's a stub.
std::istream_view<T>
— это диапазон; и, более конкретно, диапазон, сформированный как представление. Это дополнение к стандартной библиотеке похоже на то, что вы можете найти в разделе std::ranges::views
, за исключением того, что это не представление произвольного диапазона, а представление std::istream
.
Итак, какой «просмотр» применяется к std::istream
? Напомним, istream
— это поток символов, а не произвольных элементов типа T
по вашему выбору. Ленивое приложение для разбора этих символов на последовательные T
— это «просмотр» istream. То есть k-й элемент std::istream_view<T>(is)
— это то, что вы получите в k-е время работы is >> t
для t
типа T
.
Вы должны использовать std::istream_view
(осторожно), когда хотите применить свой код, который работает с диапазонами, непосредственно к входным данным - вместо того, чтобы сначала анализировать ввод в какую-либо структуру данных в более "старомодной" манере, а затем работая над этой структурой как над диапазоном.
Другие взгляды на то, что такое std::istream_view
:
T
s из istream; прочитайте этот ответ для деталей (обратите внимание, что речь идет о представлении istream в диапазонах-v3, большая часть которых стала стандартной библиотекой диапазонов).std::istream_iterator<T>
в интерфейс представления C++20».@NicolBolas: Это действительно просто пара std::istream_iterator<T>(my_istream)
и std::istream_iterator<T>()
?
Я сомневаюсь, что он использует именно эти типы, поскольку я не уверен, считаются ли они концептуальными итераторами. Но то, что вы описали, является основной идеей.
@Barry: я ошибочно предположил, что переключение типа элемента делает его непредставленным. Отредактировано.
@NicolBolas Вы можете думать об этом так, но более эффективно. istream_iterator<T>
должен иметь член T
, что означает, что копирование этого итератора должно копировать T
. Здесь istream_view<T>
— это элемент с элементом T
, а istream_view<T>::iterator
— просто элемент istream_view<T>*
, поэтому итераторы копировать дешевле.
Однако мы не часто копируем итераторы.
@AsteroidsWithWings, так что вы принимаете свои итераторы &
? Почему? Я нахожу большинство (если не всех) людей, копирующих итераторы повсюду. Позвоните all_of
, который делает что-то find_if
, и у вас будет N ^ 2 копий. Вы не используете <algorithm>
? Все эти вещи копируют итераторы.
@Fureeish Я сказал никогда? Я сказал, что передаю итераторы по адресу? Нет... Давайте избегать ложных аргументов. Как часто вы делаете all_of
с find_if
внутри? Ваш типичный вариант использования похож на std::find(begin, end, val)
, и это пара копий. Не ничего, конечно, но действительно ли это масштабная сделка?
@AsteroidsWithWings Я сказал никогда? Что останется, если не копировать их при прохождении? Сочетание all_of
с find_if
достаточно распространено, и люди, с которыми я работал (размер компании разный), упоминают об этом. «Пары копий» на вариант использования достаточно, чтобы считать «нечастое копирование итераторов» ошибкой. Не говоря уже о том, что весь общий код, который работает с итераторами, и делегаты работают с другими частями, где они снова копируются. Так что да, сделать итераторы настолько маленькими, насколько это возможно, очень сложно, просто потому, что это устоявшееся соглашение C++, согласно которому итераторы дешево копировать.
@Fureeish А копировать char
дешево. Вроде, очень. Я слышу много утверждений о том, что «это плохо», но никаких реальных данных или веских убедительных аргументов, почему это плохо. Бьюсь об заклад, вам потребовалось больше времени, чтобы написать свой последний комментарий, чем вы когда-либо сэкономили на копировании char
s, хранящихся в istream_iterator
s.
@AsteroidsWithWings проблема с абстрагированием концепции итераторов заключается в том, что все итераторы должны быть дешевыми для копирования. В этом случае следует позаботиться о том, чтобы они соответствовали этим требованиям. char
копировать всегда дешево, так что вам не нужно спорить об этом. Когда вы сравниваете char
s с iterator
s, вы говорите, что «char
s очень дешево копировать». Большой. Если мы полагаемся на то, что char
будут дешевыми для копирования, мы можем также полагаться на то, что все iterator
будут дешевыми для копирования. Условная дешевизна копирования (независимо от того, содержит ли итератор char
или string
) лишила бы свободу оптимизации.
@Fureeish Больше соломенных чучел! Никто не говорит о каком-то другом итераторе. Мы говорим об итераторах istream. Вот и все. Конец истории. Итак, это char
или, может быть, wchar_t
, которые могут состоять из четырех байтов. Вряд ли налогообложение для вашего компьютера. Вы по-прежнему не приводите здесь никаких доказательств реальной практической проблемы. Дело в том, что этот istream_view, насколько я вижу, не предлагает каких-либо существенных преимуществ в производительности, вопреки некоторым утверждениям выше. Если вы не согласны, не стесняйтесь предоставить некоторые практические доказательства!
@AsteroidsWithWings эээ ... Я даю общее представление об удобстве использования итератора ... Не хранить переменную внутри итератора, очевидно, лучше для места, чем фактически хранить ее.
@Fureeish В этом утверждении нет ничего «очевидного». Тем не менее, похоже, вы говорите о чем-то, не имеющем отношения к теме этого вопроса и ответа, так что давайте двигаться дальше.
@AsteroidsWithWings: Не принимая здесь чью-либо сторону - разве итераторы istream не сохраняют значение T
, а не char
или wchar_t
?
@einpoklum О, это хороший момент - думаю, тогда я больше думал о istreambuf_iterator
!
Более того, это обсуждение должно привести к редактированию или рекомендации по редактированию? :-\
Так что это просто
istream_iterator<T>
, завернутый в интерфейс представления C++20.