[libcxx-commits] [libcxx] 96a509b - implement `std::views::istream`

Hui Xie via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 6 14:57:48 PDT 2022


Author: Hui Xie
Date: 2022-10-06T22:57:37+01:00
New Revision: 96a509bca28b8668c3c2c68aae4116cc0d8c2952

URL: https://github.com/llvm/llvm-project/commit/96a509bca28b8668c3c2c68aae4116cc0d8c2952
DIFF: https://github.com/llvm/llvm-project/commit/96a509bca28b8668c3c2c68aae4116cc0d8c2952.diff

LOG: implement `std::views::istream`

implement `std::ranges::basic_istream_view` and `std::views::istream`. Although the view itself is constexpr,
the constructor argument is a base class std::istream where its ctor/dtor are not constexpr. So no tests are performed in
constexpr

Differential Revision: https://reviews.llvm.org/D133317

Added: 
    libcxx/include/__ranges/istream_view.h
    libcxx/test/libcxx/ranges/range.factories/range.istream.view/no_unique_address.compile.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/begin.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/cpo.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/end.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/general.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/iterator/compare.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/iterator/increment.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/iterator/member_types.compile.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/iterator/special_op.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/range.concept.compile.pass.cpp
    libcxx/test/std/ranges/range.factories/range.istream.view/utils.h

Modified: 
    libcxx/docs/Status/Cxx20Issues.csv
    libcxx/docs/Status/Cxx20Papers.csv
    libcxx/docs/Status/Cxx2bIssues.csv
    libcxx/include/CMakeLists.txt
    libcxx/include/module.modulemap.in
    libcxx/include/ranges
    libcxx/test/libcxx/private_headers.verify.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index bd93c95b8f2b1..b15142420fa2b 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -296,6 +296,6 @@
 "`3393 <https://wg21.link/LWG3393>`__","Missing/incorrect feature test macro for coroutines","Prague","|Complete|","14.0"
 "`3395 <https://wg21.link/LWG3395>`__","Definition for three-way comparison needs to be updated (US 152)","Prague","","","|spaceship|"
 "`3396 <https://wg21.link/LWG3396>`__","Clarify point of reference for ``source_location::current()``\  (DE 169)","Prague","",""
-"`3397 <https://wg21.link/LWG3397>`__","``ranges::basic_istream_view::iterator``\  should not provide ``iterator_category``\ ","Prague","","","|ranges|"
+"`3397 <https://wg21.link/LWG3397>`__","``ranges::basic_istream_view::iterator``\  should not provide ``iterator_category``\ ","Prague","|Complete|","16.0","|ranges|"
 "`3398 <https://wg21.link/LWG3398>`__","``tuple_element_t``\  is also wrong for ``const subrange``\ ","Prague","|Complete|","14.0","|ranges|"
 "`3446 <https://wg21.link/LWG3446>`__","``indirectly_readable_traits``\ ambiguity for types with both ``value_type``\ and ``element_type``\ ","November virtual meeting","|Complete|","13.0"

diff  --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
index ab7a84ba3198b..90215d3380103 100644
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -108,7 +108,7 @@
 "`P0784R7 <https://wg21.link/P0784R7>`__","CWG","More constexpr containers","Cologne","|Complete|","12.0"
 "`P0980R1 <https://wg21.link/P0980R1>`__","LWG","Making std::string constexpr","Cologne","|Complete|","15.0"
 "`P1004R2 <https://wg21.link/P1004R2>`__","LWG","Making std::vector constexpr","Cologne","|Complete|","15.0"
-"`P1035R7 <https://wg21.link/P1035R7>`__","LWG","Input Range Adaptors","Cologne","",""
+"`P1035R7 <https://wg21.link/P1035R7>`__","LWG","Input Range Adaptors","Cologne","|In Progress|",""
 "`P1065R2 <https://wg21.link/P1065R2>`__","LWG","Constexpr INVOKE","Cologne","|Complete|","12.0"
 "`P1135R6 <https://wg21.link/P1135R6>`__","LWG","The C++20 Synchronization Library","Cologne","|Complete|","11.0"
 "`P1207R4 <https://wg21.link/P1207R4>`__","LWG","Movability of Single-pass Iterators","Cologne","|Complete|","15.0"
@@ -124,7 +124,7 @@
 "`P1523R1 <https://wg21.link/P1523R1>`__","LWG","Views and Size Types","Cologne","|Complete|","15.0"
 "`P1612R1 <https://wg21.link/P1612R1>`__","LWG","Relocate Endian's Specification","Cologne","|Complete|","10.0"
 "`P1614R2 <https://wg21.link/P1614R2>`__","LWG","The Mothership has Landed","Cologne","|In Progress|",""
-"`P1638R1 <https://wg21.link/P1638R1>`__","LWG","basic_istream_view::iterator should not be copyable","Cologne","",""
+"`P1638R1 <https://wg21.link/P1638R1>`__","LWG","basic_istream_view::iterator should not be copyable","Cologne","|Complete|","16.0"
 "`P1643R1 <https://wg21.link/P1643R1>`__","LWG","Add wait/notify to atomic_ref","Cologne","",""
 "`P1644R0 <https://wg21.link/P1644R0>`__","LWG","Add wait/notify to atomic<shared_ptr>","Cologne","",""
 "`P1650R0 <https://wg21.link/P1650R0>`__","LWG","Output std::chrono::days with 'd' suffix","Cologne","",""
@@ -204,4 +204,4 @@
 "`P2372R3 <https://wg21.link/P2372R3>`__","LWG","Fixing locale handling in chrono formatters","October 2021","",""
 "`P2415R2 <https://wg21.link/P2415R2>`__","LWG","What is a ``view``","October 2021","|Complete|","14.0"
 "`P2418R2 <https://wg21.link/P2418R2>`__","LWG","Add support for ``std::generator``-like types to ``std::format``","October 2021","|Complete|","15.0"
-"`P2432R1 <https://wg21.link/P2432R1>`__","LWG","Fix ``istream_view``","October 2021","",""
+"`P2432R1 <https://wg21.link/P2432R1>`__","LWG","Fix ``istream_view``","October 2021","|Complete|","16.0"

diff  --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index 534bd7e336444..b351676642d52 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -121,7 +121,7 @@
 `3563 <https://wg21.link/LWG3563>`__,"``keys_view`` example is broken","October 2021","","","|ranges|"
 `3566 <https://wg21.link/LWG3566>`__,"Constraint recursion for ``operator<=>(optional<T>, U)``","October 2021","","","|spaceship|"
 `3567 <https://wg21.link/LWG3567>`__,"Formatting move-only iterators take two","October 2021","","","|format|"
-`3568 <https://wg21.link/LWG3568>`__,"``basic_istream_view`` needs to initialize ``value_``","October 2021","","","|ranges|"
+`3568 <https://wg21.link/LWG3568>`__,"``basic_istream_view`` needs to initialize ``value_``","October 2021","|Complete|","16.0","|ranges|"
 `3570 <https://wg21.link/LWG3570>`__,"``basic_osyncstream::emit`` should be an unformatted output function","October 2021","",""
 `3571 <https://wg21.link/LWG3571>`__,"``flush_emit`` should set ``badbit`` if the ``emit`` call fails","October 2021","",""
 `3572 <https://wg21.link/LWG3572>`__,"``copyable-box`` should be fully ``constexpr``","October 2021","|Complete|","14.0","|ranges|"

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 8e79e106a5a92..b9b657bca3bf8 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -481,6 +481,7 @@ set(files
   __ranges/enable_view.h
   __ranges/filter_view.h
   __ranges/iota_view.h
+  __ranges/istream_view.h
   __ranges/join_view.h
   __ranges/lazy_split_view.h
   __ranges/non_propagating_cache.h

diff  --git a/libcxx/include/__ranges/istream_view.h b/libcxx/include/__ranges/istream_view.h
new file mode 100644
index 0000000000000..caa29aaac23e8
--- /dev/null
+++ b/libcxx/include/__ranges/istream_view.h
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef _LIBCPP___RANGES_ISTREAM_VIEW_H
+#define _LIBCPP___RANGES_ISTREAM_VIEW_H
+
+#include <__concepts/constructible.h>
+#include <__concepts/derived_from.h>
+#include <__concepts/movable.h>
+#include <__config>
+#include <__iterator/default_sentinel.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/addressof.h>
+#include <__ranges/view_interface.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/forward.h>
+#include <cstddef>
+#include <iosfwd>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER >= 20
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+
+template <class _Val, class _CharT, class _Traits>
+concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; };
+
+template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>>
+  requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
+class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> {
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream)
+      : __stream_(std::addressof(__stream)) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto begin() {
+    *__stream_ >> __value_;
+    return __iterator{*this};
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; }
+
+private:
+  class __iterator;
+
+  basic_istream<_CharT, _Traits>* __stream_;
+  _LIBCPP_NO_UNIQUE_ADDRESS _Val __value_ = _Val();
+};
+
+template <movable _Val, class _CharT, class _Traits>
+  requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
+class basic_istream_view<_Val, _CharT, _Traits>::__iterator {
+public:
+  using iterator_concept = input_iterator_tag;
+  using 
diff erence_type  = ptr
diff _t;
+  using value_type       = _Val;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view& __parent) noexcept
+      : __parent_(std::addressof(__parent)) {}
+
+  __iterator(const __iterator&)                  = delete;
+  _LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default;
+
+  __iterator& operator=(const __iterator&)                  = delete;
+  _LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default;
+
+  _LIBCPP_HIDE_FROM_ABI __iterator& operator++() {
+    *__parent_->__stream_ >> __parent_->__value_;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI void operator++(int) { ++*this; }
+
+  _LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; }
+
+  _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __x, default_sentinel_t) {
+    return !*__x.__get_parent_stream();
+  }
+
+private:
+  basic_istream_view* __parent_;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr basic_istream<_CharT, _Traits>* __get_parent_stream() const {
+    return __parent_->__stream_;
+  }
+};
+
+template <class _Val>
+using istream_view = basic_istream_view<_Val, char>;
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <class _Val>
+using wistream_view = basic_istream_view<_Val, wchar_t>;
+#endif
+
+namespace views {
+namespace __istream {
+
+// clang-format off
+template <class _Tp>
+struct __fn {
+  template <class _Up, class _UnCVRef = remove_cvref_t<_Up>>
+    requires derived_from<_UnCVRef, basic_istream<typename _UnCVRef::char_type,
+                                                  typename _UnCVRef::traits_type>>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Up&& __u) const
+    noexcept(noexcept(basic_istream_view<_Tp, typename _UnCVRef::char_type,
+                                              typename _UnCVRef::traits_type>(std::forward<_Up>(__u))))
+    -> decltype(      basic_istream_view<_Tp, typename _UnCVRef::char_type,
+                                              typename _UnCVRef::traits_type>(std::forward<_Up>(__u)))
+    {   return        basic_istream_view<_Tp, typename _UnCVRef::char_type,
+                                              typename _UnCVRef::traits_type>(std::forward<_Up>(__u));
+    }
+};
+// clang-format on
+
+} // namespace __istream
+
+inline namespace __cpo {
+template <class _Tp>
+  inline constexpr auto istream = __istream::__fn<_Tp>{};
+} // namespace __cpo
+} // namespace views
+
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 20
+
+#endif // _LIBCPP___RANGES_ISTREAM_VIEW_H

diff  --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index dd7fd087e927a..73e366f5dc192 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1014,6 +1014,10 @@ module std [system] {
       module enable_view            { private header "__ranges/enable_view.h" }
       module filter_view            { private header "__ranges/filter_view.h" }
       module iota_view              { private header "__ranges/iota_view.h" }
+      module istream_view           {
+        @requires_LIBCXX_ENABLE_LOCALIZATION@
+        private header "__ranges/istream_view.h"
+      }
       module join_view              { private header "__ranges/join_view.h" }
       module lazy_split_view        { private header "__ranges/lazy_split_view.h" }
       module non_propagating_cache  { private header "__ranges/non_propagating_cache.h" }

diff  --git a/libcxx/include/ranges b/libcxx/include/ranges
index b2e14cdccc33d..0565b2f205268 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -228,6 +228,19 @@ namespace std::ranges {
     inline constexpr unspecified lazy_split = unspecified;
   }
 
+  // [range.istream], istream view
+  template<movable Val, class CharT, class Traits = char_traits<CharT>>
+    requires see below
+  class basic_istream_view;
+
+  template<class Val>
+    using istream_view = basic_istream_view<Val, char>;
+
+  template<class Val>
+    using wistream_view = basic_istream_view<Val, wchar_t>;
+
+  namespace views { template<class T> inline constexpr unspecified istream = unspecified; }
+
   // [range.zip], zip view
   template<input_range... Views>
     requires (view<Views> && ...) && (sizeof...(Views) > 0)
@@ -305,6 +318,10 @@ namespace std {
 #include <type_traits>
 #include <version>
 
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <__ranges/istream_view.h>
+#endif
+
 // standard-mandated includes
 
 // [ranges.syn]

diff  --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp
index 693dd1d3d15b3..90e06bdef74ef 100644
--- a/libcxx/test/libcxx/private_headers.verify.cpp
+++ b/libcxx/test/libcxx/private_headers.verify.cpp
@@ -512,6 +512,7 @@ END-SCRIPT
 #include <__ranges/enable_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/enable_view.h'}}
 #include <__ranges/filter_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/filter_view.h'}}
 #include <__ranges/iota_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/iota_view.h'}}
+#include <__ranges/istream_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/istream_view.h'}}
 #include <__ranges/join_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/join_view.h'}}
 #include <__ranges/lazy_split_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/lazy_split_view.h'}}
 #include <__ranges/non_propagating_cache.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/non_propagating_cache.h'}}

diff  --git a/libcxx/test/libcxx/ranges/range.factories/range.istream.view/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.factories/range.istream.view/no_unique_address.compile.pass.cpp
new file mode 100644
index 0000000000000..f2fd2d628bc1d
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.factories/range.istream.view/no_unique_address.compile.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// clang-cl and cl currently don't support [[no_unique_address]]
+// XFAIL: msvc
+
+// Test the libc++ extension that the value stored in `std::ranges::istream_view` has been marked
+// as _LIBCPP_NO_UNIQUE_ADDRESS
+
+#include <istream>
+#include <ranges>
+
+struct Empty {
+  friend std::istream& operator>>(std::istream& i, Empty const&) { return i; }
+};
+
+static_assert(sizeof(std::ranges::istream_view<Empty>) == sizeof(void*));
+

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/begin.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/begin.pass.cpp
new file mode 100644
index 0000000000000..99891bcbfbae7
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/begin.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// constexpr auto begin();
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "utils.h"
+
+template <class T>
+concept HasBegin = requires(T t) { t.begin(); };
+
+static_assert(HasBegin<std::ranges::istream_view<int>>);
+static_assert(!HasBegin<const std::ranges::istream_view<int>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(HasBegin<std::ranges::wistream_view<int>>);
+static_assert(!HasBegin<const std::ranges::wistream_view<int>>);
+#endif
+
+template <class CharT>
+void test() {
+  // begin should read the first element
+  {
+    auto iss = make_string_stream<CharT>("12    3");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(*it == 12);
+  }
+
+  // empty stream
+  {
+    auto iss = make_string_stream<CharT>("");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(it == isv.end());
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/cpo.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/cpo.pass.cpp
new file mode 100644
index 0000000000000..1cbbccfdbe43e
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/cpo.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::istream<T>
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "utils.h"
+
+static_assert(!std::is_invocable_v<decltype((std::views::istream<int>))>);
+static_assert(std::is_invocable_v<decltype((std::views::istream<int>)), std::istream&>);
+static_assert(!std::is_invocable_v<decltype((std::views::istream<int>)), const std::istream&>);
+static_assert(!std::is_invocable_v<decltype((std::views::istream<int>)), int>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(std::is_invocable_v<decltype((std::views::istream<int>)), std::wistream&>);
+static_assert(!std::is_invocable_v<decltype((std::views::istream<int>)), const std::wistream&>);
+#endif
+
+template <class CharT>
+void test() {
+  auto iss = make_string_stream<CharT>("12   3");
+  auto isv = std::views::istream<int>(iss);
+  auto it  = isv.begin();
+  assert(*it == 12);
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp
new file mode 100644
index 0000000000000..ff60fbff1d73b
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/ctor.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "utils.h"
+
+// test that the constructor is explicit
+static_assert(std::constructible_from<std::ranges::istream_view<int>, std::istream&>);
+static_assert(!std::convertible_to<std::istream&, std::ranges::istream_view<int>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(std::constructible_from<std::ranges::wistream_view<int>, std::wistream&>);
+static_assert(!std::convertible_to<std::wistream&, std::ranges::wistream_view<int>>);
+#endif
+
+template <class CharT>
+void test() {
+  // test constructor init the stream pointer to the passed one
+  {
+    auto iss = make_string_stream<CharT>("123");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(*it == 123);
+  }
+
+  // LWG 3568. basic_istream_view needs to initialize value_
+  {
+    auto iss = make_string_stream<CharT>("123");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    using Iter = std::ranges::iterator_t<decltype(isv)>;
+    Iter iter{isv};
+    assert(*iter == 0);
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/end.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/end.pass.cpp
new file mode 100644
index 0000000000000..80b1dfe2755d1
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/end.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// constexpr default_sentinel_t end() const noexcept;
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "utils.h"
+
+template <class T>
+concept NoexceptEnd =
+    requires(T t) {
+      { t.end() } noexcept;
+    };
+
+static_assert(NoexceptEnd<std::ranges::istream_view<int>>);
+static_assert(NoexceptEnd<const std::ranges::istream_view<int>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(NoexceptEnd<std::ranges::wistream_view<int>>);
+static_assert(NoexceptEnd<const std::ranges::wistream_view<int>>);
+#endif
+
+template <class CharT>
+void test() {
+  auto iss = make_string_stream<CharT>("12");
+  std::ranges::basic_istream_view<int, CharT> isv{iss};
+  [[maybe_unused]] std::same_as<std::default_sentinel_t> auto sent = isv.end();
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/general.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/general.pass.cpp
new file mode 100644
index 0000000000000..c65f10cd78532
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/general.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// Some basic examples of how istream_view might be used in the wild. This is a general
+// collection of sample algorithms and functions that try to mock general usage of
+// this view.
+
+#include <algorithm>
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "utils.h"
+
+template <class CharT>
+void test() {
+  auto ints      = make_string_stream<CharT>("0 1  2   3     4");
+  auto oss       = std::basic_ostringstream<CharT>{};
+  auto delimiter = make_string<CharT>("-");
+  std::ranges::copy(
+      std::ranges::basic_istream_view<int, CharT>(ints), std::ostream_iterator<int, CharT>{oss, delimiter.c_str()});
+  auto expected = make_string<CharT>("0-1-2-3-4-");
+  assert(oss.str() == expected);
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/compare.pass.cpp
new file mode 100644
index 0000000000000..81ae0882eb64a
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/compare.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// friend bool operator==(const iterator& x, default_sentinel_t);
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "../utils.h"
+
+template <class CharT>
+void test() {
+  // fail to read
+  {
+    auto iss = make_string_stream<CharT>("a123 4");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(it == std::default_sentinel);
+  }
+
+  // iterate through the end
+  {
+    auto iss = make_string_stream<CharT>("123 ");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(it != std::default_sentinel);
+    ++it;
+    assert(it == std::default_sentinel);
+  }
+
+  // empty stream
+  {
+    auto iss = make_string_stream<CharT>("");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(it == std::default_sentinel);
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp
new file mode 100644
index 0000000000000..017d11c3e6588
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/ctor.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// constexpr explicit iterator(basic_istream_view& parent) noexcept;
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "../utils.h"
+
+// test that the constructor is explicit
+template <class CharT>
+using IstreamView = std::ranges::basic_istream_view<int, CharT>;
+template <class CharT>
+using Iter = std::ranges::iterator_t<IstreamView<CharT>>;
+
+static_assert(std::constructible_from<Iter<char>, IstreamView<char>&>);
+static_assert(!std::convertible_to<IstreamView<char>&, Iter<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(std::constructible_from<Iter<wchar_t>, IstreamView<wchar_t>&>);
+static_assert(!std::convertible_to<IstreamView<wchar_t>&, Iter<wchar_t>>);
+#endif
+
+// test that the constructor is noexcept
+static_assert(std::is_nothrow_constructible_v<Iter<char>, IstreamView<char>&>);
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(std::is_nothrow_constructible_v<Iter<wchar_t>, IstreamView<wchar_t>&>);
+#endif
+
+template <class CharT>
+void test() {
+  auto iss = make_string_stream<CharT>("123");
+  std::ranges::basic_istream_view<int, CharT> isv{iss};
+  Iter<CharT> it{isv};
+  ++it;
+  assert(*it == 123);
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
new file mode 100644
index 0000000000000..1cf05f0ac4cbe
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/deref.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// Val& operator*() const;
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "../utils.h"
+
+template <class CharT>
+void test() {
+  // operator* should return correct value
+  {
+    auto iss = make_string_stream<CharT>("1 2 345 ");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it                              = isv.begin();
+    std::same_as<int&> decltype(auto) v1 = *it;
+    assert(v1 == 1);
+  }
+
+  // operator* should return the same reference to the value stored in the view
+  {
+    auto iss = make_string_stream<CharT>("1 2 345 ");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    using Iter = std::ranges::iterator_t<decltype(isv)>;
+
+    Iter it1{isv};
+    Iter it2{isv};
+    assert(&*it1 == &*it2);
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/increment.pass.cpp
new file mode 100644
index 0000000000000..667547827dd66
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/increment.pass.cpp
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// iterator& operator++();
+// void operator++(int);
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "../utils.h"
+
+template <class CharT>
+void test() {
+  // operator ++()
+  {
+    auto iss = make_string_stream<CharT>("1 2 345 ");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(*it == 1);
+
+    std::same_as<decltype(it)&> decltype(auto) it2 = ++it;
+    assert(&it2 == &it);
+    assert(*it2 == 2);
+
+    ++it2;
+    assert(*it2 == 345);
+
+    ++it2;
+    assert(it2 == isv.end());
+  }
+
+  // operator ++(int)
+  {
+    auto iss = make_string_stream<CharT>("1 2 345 ");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it = isv.begin();
+    assert(*it == 1);
+
+    static_assert(std::same_as<decltype(it++), void>);
+    it++;
+    assert(*it == 2);
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/member_types.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/member_types.compile.pass.cpp
new file mode 100644
index 0000000000000..1e9924fe99d16
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/member_types.compile.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// Member typedefs in istream_view<T>::<iterator>.
+
+#include <istream>
+#include <ranges>
+
+#include "test_macros.h"
+
+template <class T>
+concept HasIterCategory = requires { typename T::iterator_category; };
+
+struct MemberIteratorCategory {
+  using iterator_category = std::input_iterator_tag;
+};
+static_assert(HasIterCategory<MemberIteratorCategory>);
+
+template <class Val, class CharT>
+void test() {
+  using Iter = std::ranges::iterator_t<std::ranges::basic_istream_view<Val, CharT>>;
+  static_assert(std::is_same_v<typename Iter::iterator_concept, std::input_iterator_tag>);
+  static_assert(std::is_same_v<typename Iter::
diff erence_type, std::ptr
diff _t>);
+  static_assert(std::is_same_v<typename Iter::value_type, Val>);
+  static_assert(!HasIterCategory<Iter>);
+}
+
+template <class CharT>
+void testOne() {
+  test<int, CharT>();
+  test<long, CharT>();
+  test<double, CharT>();
+  test<CharT, CharT>();
+}
+
+void test() {
+  testOne<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  testOne<wchar_t>();
+#endif
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/special_op.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/special_op.pass.cpp
new file mode 100644
index 0000000000000..edcf6ebe8f82a
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/iterator/special_op.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+//    iterator(const iterator&) = delete;
+//    iterator(iterator&&) = default;
+//    iterator& operator=(const iterator&) = delete;
+//    iterator& operator=(iterator&&) = default;
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+#include "test_macros.h"
+#include "../utils.h"
+
+template <class CharT>
+using Iter = std::ranges::iterator_t<std::ranges::basic_istream_view<int, CharT>>;
+static_assert(!std::copy_constructible<Iter<char>>);
+static_assert(!std::is_copy_assignable_v<Iter<char>>);
+static_assert(std::move_constructible<Iter<char>>);
+static_assert(std::is_move_assignable_v<Iter<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(!std::copy_constructible<Iter<wchar_t>>);
+static_assert(!std::is_copy_assignable_v<Iter<wchar_t>>);
+static_assert(std::move_constructible<Iter<wchar_t>>);
+static_assert(std::is_move_assignable_v<Iter<wchar_t>>);
+#endif
+
+template <class CharT>
+void test() {
+  // test move constructor
+  {
+    auto iss = make_string_stream<CharT>("12   3");
+    std::ranges::basic_istream_view<int, CharT> isv{iss};
+    auto it  = isv.begin();
+    auto it2 = std::move(it);
+    assert(*it2 == 12);
+  }
+
+  // test move assignment
+  {
+    auto iss1 = make_string_stream<CharT>("12   3");
+    std::ranges::basic_istream_view<int, CharT> isv1{iss1};
+    auto iss2 = make_string_stream<CharT>("45   6");
+    std::ranges::basic_istream_view<int, CharT> isv2{iss2};
+
+    auto it1 = isv1.begin();
+    assert(*it1 == 12);
+    it1 = isv2.begin();
+    assert(*it1 == 45);
+  }
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/range.concept.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.istream.view/range.concept.compile.pass.cpp
new file mode 100644
index 0000000000000..9141632bab744
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/range.concept.compile.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-localization
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// concept checking istream_view
+
+#include <istream>
+#include <ranges>
+
+#include "test_macros.h"
+
+template <class Val, class CharT, class Traits = std::char_traits<CharT>>
+concept HasIstreamView = requires { typename std::ranges::basic_istream_view<Val, CharT, Traits>; };
+
+static_assert(HasIstreamView<int, char>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(HasIstreamView<int, wchar_t>);
+#endif
+
+// Unmovable Val
+struct Unmovable {
+  Unmovable()            = default;
+  Unmovable(Unmovable&&) = delete;
+  template <class CharT>
+  friend std::basic_istream<CharT>& operator>>(std::basic_istream<CharT>& x, const Unmovable&) {
+    return x;
+  }
+};
+static_assert(!HasIstreamView<Unmovable, char>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(!HasIstreamView<Unmovable, wchar_t>);
+#endif
+
+// !default_initializable<Val>
+struct NoDefaultCtor {
+  NoDefaultCtor(int) {}
+  friend std::istream& operator>>(std::istream& x, const NoDefaultCtor&) { return x; }
+};
+static_assert(!HasIstreamView<NoDefaultCtor, char>);
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(!HasIstreamView<NoDefaultCtor, wchar_t>);
+#endif
+
+// !stream-extractable<Val, CharT, Traits>
+struct Foo {};
+static_assert(!HasIstreamView<Foo, char>);
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(!HasIstreamView<Foo, wchar_t>);
+#endif
+
+template <class T>
+concept OnlyInputRange = std::ranges::input_range<T> && !std::ranges::forward_range<T>;
+
+static_assert(OnlyInputRange<std::ranges::istream_view<int>>);
+static_assert(OnlyInputRange<std::ranges::istream_view<long>>);
+static_assert(OnlyInputRange<std::ranges::istream_view<double>>);
+static_assert(OnlyInputRange<std::ranges::istream_view<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(OnlyInputRange<std::ranges::wistream_view<int>>);
+static_assert(OnlyInputRange<std::ranges::wistream_view<long>>);
+static_assert(OnlyInputRange<std::ranges::wistream_view<double>>);
+static_assert(OnlyInputRange<std::ranges::wistream_view<wchar_t>>);
+#endif

diff  --git a/libcxx/test/std/ranges/range.factories/range.istream.view/utils.h b/libcxx/test/std/ranges/range.factories/range.istream.view/utils.h
new file mode 100644
index 0000000000000..ec6ed4daf37c2
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.istream.view/utils.h
@@ -0,0 +1,21 @@
+#ifndef TEST_STD_RANGES_RANGE_FACTORIES_RANGE_ISTREAM_UTILS_H
+#define TEST_STD_RANGES_RANGE_FACTORIES_RANGE_ISTREAM_UTILS_H
+
+#include <sstream>
+#include <string>
+
+template <class CharT, std::size_t N>
+auto make_string(const char (&in)[N]) {
+  std::basic_string<CharT> r(N - 1, static_cast<CharT>(0));
+  for (std::size_t i = 0; i < N - 1; ++i) {
+    r[i] = static_cast<CharT>(in[i]);
+  }
+  return r;
+}
+
+template <class CharT, std::size_t N>
+auto make_string_stream(const char (&in)[N]) {
+  return std::basic_istringstream<CharT>(make_string<CharT>(in));
+}
+
+#endif //TEST_STD_RANGES_RANGE_FACTORIES_RANGE_ISTREAM_UTILS_H


        


More information about the libcxx-commits mailing list