On Fri, 7 Feb 2020, Jonathan Wakely wrote: > On 06/02/20 19:52 -0500, Patrick Palka wrote: > > This patch adds ranges::basic_istream_view and ranges::istream_view. This > > seems > > to be the last missing part of the ranges header. > > > > libstdc++-v3/ChangeLog: > > > > * include/std/ranges (ranges::__detail::__stream_extractable, > > ranges::basic_istream_view, ranges::istream_view): Define. > > * testsuite/std/ranges/istream_view: New test. > > --- > > libstdc++-v3/include/std/ranges | 94 +++++++++++++++++++ > > .../testsuite/std/ranges/istream_view.cc | 76 +++++++++++++++ > > 2 files changed, 170 insertions(+) > > create mode 100644 libstdc++-v3/testsuite/std/ranges/istream_view.cc > > > > diff --git a/libstdc++-v3/include/std/ranges > > b/libstdc++-v3/include/std/ranges > > index 8a8fefb6f19..88b98310ef9 100644 > > --- a/libstdc++-v3/include/std/ranges > > +++ b/libstdc++-v3/include/std/ranges > > @@ -951,6 +951,100 @@ namespace views > > inline constexpr _Iota iota{}; > > } // namespace views > > > > + namespace __detail > > + { > > + template<typename _Val, typename _CharT, typename _Traits> > > + concept __stream_extractable > > + = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; }; > > I was going to ask for "is" and "t" to use reserved names, but those > names are actually reserved. std::ctype::is is present since C++98 and > std::binomial_distribution::t() since C++11. So the names are OK.
Phew! :) I just forgot to uglify those names. > > > + } // namespace __detail > > + > > + template<movable _Val, typename _CharT, typename _Traits> > > + requires default_initializable<_Val> > > + && __detail::__stream_extractable<_Val, _CharT, _Traits> > > + class basic_istream_view > > + : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> > > + { > > + public: > > + basic_istream_view() = default; > > + > > + constexpr explicit > > + basic_istream_view(basic_istream<_CharT, _Traits>& __stream) > > + : _M_stream(std::__addressof(__stream)) > > + { } > > + > > + constexpr auto > > + begin() > > + { > > + if (_M_stream != nullptr) > > + *_M_stream >> _M_object; > > + return _Iterator{*this}; > > + } > > + > > + constexpr default_sentinel_t > > + end() const noexcept > > + { return default_sentinel; } > > + > > + private: > > + basic_istream<_CharT, _Traits>* _M_stream = nullptr; > > + _Val _M_object = _Val(); > > + > > + struct _Iterator > > + { > > + public: > > + using iterator_category = input_iterator_tag; > > + using difference_type = ptrdiff_t; > > + using value_type = _Val; > > + > > + _Iterator() = default; > > + > > + constexpr explicit > > + _Iterator(basic_istream_view& __parent) noexcept > > + : _M_parent(std::__addressof(__parent)) > > + { } > > + > > + _Iterator(const _Iterator&) = delete; > > + _Iterator(_Iterator&&) = default; > > + _Iterator& operator=(const _Iterator&) = delete; > > + _Iterator& operator=(_Iterator&&) = default; > > + > > + _Iterator& > > + operator++() > > + { > > + __glibcxx_assert(_M_parent->_M_stream != nullptr); > > + *_M_parent->_M_stream >> _M_parent->_M_object; > > + } > > + > > + void > > + operator++(int) > > + { ++*this; } > > + > > + _Val& > > + operator*() const > > + { > > + __glibcxx_assert(_M_parent->_M_stream != nullptr); > > + return _M_parent->_M_object; > > + } > > + > > + friend bool > > + operator==(const _Iterator& __x, default_sentinel_t) > > + { return __x.__at_end(); } > > + > > + private: > > + basic_istream_view* _M_parent = nullptr; > > + > > + bool > > + __at_end() const > > Please rename this to _M_at_end for consistency with the rest of the > library. > > OK for master with that tweak, thanks. Fixed and committed with that change. Thanks for the review!