[PATCH] Partial implementation of C++20 of <ranges> header

Jonathan Wakely jwakely@redhat.com
Thu Oct 31 21:57:00 GMT 2019


	* doc/doxygen/user.cfg.in: Add new header.
	* include/Makefile.am: Add new header.
	* include/Makefile.in: Regenerate.
	* include/precompiled/stdc++.h: Include new header.
	* include/std/ranges: New header.
	(ranges::sentinel_t, ranges::range_value_t, ranges::range_reference_t)
	(ranges::range_rvalue_reference_t, ranges::sized_range)
	(ranges::output_range, ranges::input_ranges, ranges::forward_range)
	(ranges::bidirectional_range, ranges::random_access_range)
	(ranges::contiguous_range, ranges::common::range): Define.
	* testsuite/24_iterators/headers/iterator/synopsis_c++20.cc: Check
	that disabled_sized_sentinel can be specialized.
	* testsuite/std/ranges/access/begin.cc: Include <ranges> instead of
	<iterator>.
	* testsuite/std/ranges/access/cbegin.cc: Likewise.
	* testsuite/std/ranges/access/cdata.cc: Likewise.
	* testsuite/std/ranges/access/cend.cc: Likewise.
	* testsuite/std/ranges/access/crbegin.cc: Likewise.
	* testsuite/std/ranges/access/crend.cc: Likewise.
	* testsuite/std/ranges/access/data.cc: Likewise.
	* testsuite/std/ranges/access/empty.cc: Likewise.
	* testsuite/std/ranges/access/end.cc: Likewise.
	* testsuite/std/ranges/access/end_neg.cc: Likewise.
	* testsuite/std/ranges/access/rbegin.cc: Likewise.
	* testsuite/std/ranges/access/rend.cc: Likewise.
	* testsuite/std/ranges/access/size.cc: Likewise.
	* testsuite/std/ranges/access/size_neg.cc: Likewise.
	* testsuite/std/ranges/headers/ranges/synopsis.cc: New test.
	* testsuite/std/ranges/range.cc: New test.
	* testsuite/std/ranges/refinements.cc: New test.
	* testsuite/std/ranges/sized.cc: New test.
	* testsuite/util/testsuite_iterators.h: Add aliases for range types.
	(output_iterator_wrapper::WritableObject::operator=): Add const
	qualifier so that output_iterator_wrapper satisfies writable.

I have lots more of this header written, but I need to finish writing
the tests. This is a start.

Tested powerpc64le-linux, committed to trunk.


-------------- next part --------------
commit 30d052cfd06792c8c317b69129b5ca9031b90391
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Oct 31 19:42:03 2019 +0000

    Partial implementation of C++20 of <ranges> header
    
            * doc/doxygen/user.cfg.in: Add new header.
            * include/Makefile.am: Add new header.
            * include/Makefile.in: Regenerate.
            * include/precompiled/stdc++.h: Include new header.
            * include/std/ranges: New header.
            (ranges::sentinel_t, ranges::range_value_t, ranges::range_reference_t)
            (ranges::range_rvalue_reference_t, ranges::sized_range)
            (ranges::output_range, ranges::input_ranges, ranges::forward_range)
            (ranges::bidirectional_range, ranges::random_access_range)
            (ranges::contiguous_range, ranges::common::range): Define.
            * testsuite/24_iterators/headers/iterator/synopsis_c++20.cc: Check
            that disabled_sized_sentinel can be specialized.
            * testsuite/std/ranges/access/begin.cc: Include <ranges> instead of
            <iterator>.
            * testsuite/std/ranges/access/cbegin.cc: Likewise.
            * testsuite/std/ranges/access/cdata.cc: Likewise.
            * testsuite/std/ranges/access/cend.cc: Likewise.
            * testsuite/std/ranges/access/crbegin.cc: Likewise.
            * testsuite/std/ranges/access/crend.cc: Likewise.
            * testsuite/std/ranges/access/data.cc: Likewise.
            * testsuite/std/ranges/access/empty.cc: Likewise.
            * testsuite/std/ranges/access/end.cc: Likewise.
            * testsuite/std/ranges/access/end_neg.cc: Likewise.
            * testsuite/std/ranges/access/rbegin.cc: Likewise.
            * testsuite/std/ranges/access/rend.cc: Likewise.
            * testsuite/std/ranges/access/size.cc: Likewise.
            * testsuite/std/ranges/access/size_neg.cc: Likewise.
            * testsuite/std/ranges/headers/ranges/synopsis.cc: New test.
            * testsuite/std/ranges/range.cc: New test.
            * testsuite/std/ranges/refinements.cc: New test.
            * testsuite/std/ranges/sized.cc: New test.
            * testsuite/util/testsuite_iterators.h: Add aliases for range types.
            (output_iterator_wrapper::WritableObject::operator=): Add const
            qualifier so that output_iterator_wrapper satisfies writable.

diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index 3c0295d99a5..42001016721 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -829,6 +829,7 @@ INPUT                  = @srcdir@/doc/doxygen/doxygroups.cc \
                          include/ostream \
                          include/queue \
                          include/random \
+                         include/ranges \
                          include/ratio \
                          include/regex \
                          include/scoped_allocator \
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 401c87ad103..3e526dc14b7 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -64,6 +64,7 @@ std_headers = \
 	${std_srcdir}/ostream \
 	${std_srcdir}/queue \
 	${std_srcdir}/random \
+	${std_srcdir}/ranges \
 	${std_srcdir}/ratio \
 	${std_srcdir}/regex \
 	${std_srcdir}/scoped_allocator \
diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h
index fefd6e76845..57c3e2e32ee 100644
--- a/libstdc++-v3/include/precompiled/stdc++.h
+++ b/libstdc++-v3/include/precompiled/stdc++.h
@@ -138,7 +138,7 @@
 // #include <compare>
 #include <concepts>
 #include <numbers>
-// #include <ranges>
+#include <ranges>
 #include <span>
 // #include <syncstream>
 #include <version>
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
new file mode 100644
index 00000000000..884fa1d1408
--- /dev/null
+++ b/libstdc++-v3/include/std/ranges
@@ -0,0 +1,112 @@
+// <ranges> -*- C++ -*-
+
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received __a copy of the GNU General Public License and
+// __a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/ranges
+ *  This is a Standard C++ Library header.
+ *  @ingroup concepts
+ */
+
+#ifndef _GLIBCXX_RANGES
+#define _GLIBCXX_RANGES 1
+
+#if __cplusplus > 201703L
+
+#pragma GCC system_header
+
+#include <concepts>
+
+#if __cpp_lib_concepts
+
+#include <iterator>
+
+/**
+ * @defgroup ranges Ranges
+ *
+ * Components for dealing with ranges of elements.
+ */
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace ranges
+{
+  // [range.range] The range concept.
+  // Defined in <bits/range_iterator.h>
+  // template<typename> concept range;
+
+  template<range _Range>
+    using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
+
+  template<range _Range>
+    using range_value_t = iter_value_t<iterator_t<_Range>>;
+
+  template<range _Range>
+    using range_reference_t = iter_reference_t<iterator_t<_Range>>;
+
+  template<range _Range>
+    using range_rvalue_reference_t
+      = iter_rvalue_reference_t<iterator_t<_Range>>;
+
+  // [range.sized] The sized_range concept.
+  // Defined in <bits/range_iterator.h>
+  // template<typename> concept sized_range;
+
+  // [range.refinements]
+
+  template<typename _Range, typename _Tp>
+    concept output_range
+      = range<_Range> && output_iterator<iterator_t<_Range>, _Tp>;
+
+  template<typename _Tp>
+    concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
+
+  template<typename _Tp>
+    concept forward_range
+      = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
+
+  template<typename _Tp>
+    concept bidirectional_range
+      = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
+
+  template<typename _Tp>
+    concept random_access_range
+      = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
+
+  template<typename _Tp>
+    concept contiguous_range
+      = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>>
+      && requires(_Tp& __t)
+      {
+	{ ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
+      };
+
+  template<typename _Tp>
+    concept common_range
+      = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
+} // namespace ranges
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif // library concepts
+#endif // C++2a
+#endif /* _GLIBCXX_RANGES */
diff --git a/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc b/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc
index 2dbfb767fdb..824b0b4f38c 100644
--- a/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc
+++ b/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc
@@ -78,6 +78,9 @@ namespace std
   struct unreachable_sentinel_t;
 }
 
+struct I { };
+template<> constexpr bool std::disable_sized_sentinel<I, I> = true;
+
 namespace __gnu_test
 {
   // customization points
diff --git a/libstdc++-v3/testsuite/std/ranges/access/begin.cc b/libstdc++-v3/testsuite/std/ranges/access/begin.cc
index 100dcf69c6e..e4c245a76bb 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/begin.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/begin.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator> // N.B. should be <ranges>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc b/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc
index 34dd7fec3c6..54db3658896 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/cbegin.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator> // N.B. should be <ranges>
+#include <ranges>
 #include <testsuite_hooks.h>
 using std::same_as;
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/cdata.cc b/libstdc++-v3/testsuite/std/ranges/access/cdata.cc
index 9a1ab5b9607..b16c99607a5 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/cdata.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/cdata.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 
 void
diff --git a/libstdc++-v3/testsuite/std/ranges/access/cend.cc b/libstdc++-v3/testsuite/std/ranges/access/cend.cc
index 94349c35d51..3b57b3dbcaf 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/cend.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/cend.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator> // N.B. should be <ranges>
+#include <ranges>
 #include <testsuite_hooks.h>
 
 using std::same_as;
diff --git a/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc b/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc
index 24939ac658e..d9e5b0cbef7 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/crbegin.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/crend.cc b/libstdc++-v3/testsuite/std/ranges/access/crend.cc
index ef0fb0e6b09..e56491973b2 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/crend.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/crend.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/data.cc b/libstdc++-v3/testsuite/std/ranges/access/data.cc
index d9129d055fc..49321640182 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/data.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/data.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/empty.cc b/libstdc++-v3/testsuite/std/ranges/access/empty.cc
index 64b1e1b5e1b..9d6aa282142 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/empty.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/empty.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator> // N.B. should be <ranges>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/end.cc b/libstdc++-v3/testsuite/std/ranges/access/end.cc
index 6638bb35721..ed269c5433f 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/end.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/end.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator> // N.B. should be <ranges>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc b/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc
index a2a8fb05f92..0b40d274567 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do compile { target c++2a } }
 
-#include <iterator> // N.B. should be <ranges>
+#include <ranges>
 
 extern int unbounded[];
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc b/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc
index 6cfc1a38122..067ddd7ced6 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/rbegin.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/rend.cc b/libstdc++-v3/testsuite/std/ranges/access/rend.cc
index 2192825708a..17caa9fb31a 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/rend.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/rend.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/size.cc b/libstdc++-v3/testsuite/std/ranges/access/size.cc
index b0a27ca2a87..6e9af7942ec 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/size.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/size.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
-#include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
 
diff --git a/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc b/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc
index 0ba8d81874f..65fce104ff6 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc
@@ -18,7 +18,7 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do compile { target c++2a } }
 
-#include <iterator> // N.B. should be <ranges>
+#include <ranges>
 
 extern int unbounded[];
 
diff --git a/libstdc++-v3/testsuite/std/ranges/headers/ranges/synopsis.cc b/libstdc++-v3/testsuite/std/ranges/headers/ranges/synopsis.cc
new file mode 100644
index 00000000000..d4596cc8db5
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/headers/ranges/synopsis.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ranges>
+
+struct R { };
+template<> constexpr bool std::ranges::disable_sized_range<R> = true;
+
+namespace __gnu_test
+{
+  constexpr const bool* disable_sized_range
+    = &std::ranges::disable_sized_range<void>;
+  constexpr auto* begin = &std::ranges::begin;
+  constexpr auto* end = &std::ranges::end;
+  constexpr auto* cbegin = &std::ranges::cbegin;
+  constexpr auto* cend = &std::ranges::cend;
+  constexpr auto* rbegin = &std::ranges::rbegin;
+  constexpr auto* rend = &std::ranges::rend;
+  constexpr auto* crbegin = &std::ranges::crbegin;
+  constexpr auto* crend = &std::ranges::crend;
+}
diff --git a/libstdc++-v3/testsuite/std/ranges/range.cc b/libstdc++-v3/testsuite/std/ranges/range.cc
new file mode 100644
index 00000000000..44869de3ffb
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/range.cc
@@ -0,0 +1,89 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ranges>
+#include <testsuite_iterators.h>
+
+static_assert( std::ranges::range<int(&)[1]> );
+static_assert( std::ranges::range<const int(&)[1]> );
+static_assert( std::ranges::range<int[1]> );
+static_assert( !std::ranges::range<int*> );
+
+using namespace __gnu_test;
+
+static_assert( std::ranges::range<test_contiguous_range<int>> );
+static_assert( std::ranges::range<test_contiguous_range<int>&> );
+static_assert( std::ranges::range<test_random_access_range<int>> );
+static_assert( std::ranges::range<test_random_access_range<int>&> );
+static_assert( std::ranges::range<test_bidirectional_range<int>> );
+static_assert( std::ranges::range<test_bidirectional_range<int>&> );
+static_assert( std::ranges::range<test_forward_range<int>> );
+static_assert( std::ranges::range<test_forward_range<int>&> );
+static_assert( std::ranges::range<test_input_range<int>> );
+static_assert( std::ranges::range<test_input_range<int>&> );
+static_assert( std::ranges::range<test_output_range<int>> );
+static_assert( std::ranges::range<test_output_range<int>&> );
+
+static_assert( std::ranges::range<test_contiguous_sized_range<int>> );
+static_assert( std::ranges::range<test_contiguous_sized_range<int>&> );
+static_assert( std::ranges::range<test_random_access_sized_range<int>> );
+static_assert( std::ranges::range<test_random_access_sized_range<int>&> );
+static_assert( std::ranges::range<test_bidirectional_sized_range<int>> );
+static_assert( std::ranges::range<test_bidirectional_sized_range<int>&> );
+static_assert( std::ranges::range<test_forward_sized_range<int>> );
+static_assert( std::ranges::range<test_forward_sized_range<int>&> );
+static_assert( std::ranges::range<test_input_sized_range<int>> );
+static_assert( std::ranges::range<test_input_sized_range<int>&> );
+static_assert( std::ranges::range<test_output_sized_range<int>> );
+static_assert( std::ranges::range<test_output_sized_range<int>&> );
+
+using std::same_as;
+
+using C = test_contiguous_range<char>;
+using I = test_input_range<char>;
+using O = test_output_range<char>;
+
+static_assert( same_as<std::ranges::iterator_t<C>,
+		       contiguous_iterator_wrapper<char>> );
+static_assert( same_as<std::ranges::iterator_t<O>,
+		       decltype(std::declval<O&>().begin())> );
+
+static_assert( same_as<std::ranges::sentinel_t<C>,
+		       contiguous_iterator_wrapper<char>> );
+static_assert( same_as<std::ranges::sentinel_t<O>,
+		       decltype(std::declval<O&>().end())> );
+
+static_assert( same_as<std::ranges::range_difference_t<C>,
+		       std::ptrdiff_t> );
+static_assert( same_as<std::ranges::range_difference_t<O>,
+		       std::ptrdiff_t> );
+
+static_assert( same_as<std::ranges::range_value_t<O>,
+		       char> );
+
+static_assert( same_as<std::ranges::range_reference_t<I>,
+		       char&> );
+static_assert( same_as<std::ranges::range_reference_t<O>,
+		       WritableObject<char>> );
+
+static_assert( same_as<std::ranges::range_rvalue_reference_t<I>,
+		       char&&> );
+static_assert( same_as<std::ranges::range_rvalue_reference_t<O>,
+		      WritableObject<char>> );
diff --git a/libstdc++-v3/testsuite/std/ranges/refinements.cc b/libstdc++-v3/testsuite/std/ranges/refinements.cc
new file mode 100644
index 00000000000..0b315397944
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/refinements.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ranges>
+#include <testsuite_iterators.h>
+
+static_assert( std::ranges::output_range<int(&)[1], int> );
+static_assert( ! std::ranges::output_range<const int(&)[1], int> );
+static_assert( std::ranges::output_range<int[1], int> );
+static_assert( ! std::ranges::output_range<int[1], int*> );
+
+static_assert( std::ranges::input_range<int(&)[1]> );
+static_assert( std::ranges::input_range<const int(&)[1]> );
+static_assert( std::ranges::input_range<int[1]> );
+
+static_assert( std::ranges::contiguous_range<int(&)[1]> );
+static_assert( std::ranges::contiguous_range<const int(&)[1]> );
+static_assert( std::ranges::contiguous_range<int[1]> );
+
+using namespace __gnu_test;
+
+static_assert( std::ranges::output_range<test_contiguous_range<int>, int> );
+static_assert( std::ranges::output_range<test_random_access_range<int>, int> );
+static_assert( std::ranges::output_range<test_bidirectional_range<int>, int> );
+static_assert( std::ranges::output_range<test_forward_range<int>, int> );
+static_assert( ! std::ranges::output_range<test_input_range<int>, int> );
+static_assert( std::ranges::output_range<test_output_range<int>, int> );
+
+static_assert( std::ranges::input_range<test_contiguous_range<int>> );
+static_assert( std::ranges::input_range<test_random_access_range<int>> );
+static_assert( std::ranges::input_range<test_bidirectional_range<int>> );
+static_assert( std::ranges::input_range<test_forward_range<int>> );
+static_assert( std::ranges::input_range<test_input_range<int>> );
+static_assert( ! std::ranges::input_range<test_output_range<int>> );
+
+static_assert( std::ranges::forward_range<test_contiguous_range<int>> );
+static_assert( std::ranges::forward_range<test_random_access_range<int>> );
+static_assert( std::ranges::forward_range<test_bidirectional_range<int>> );
+static_assert( std::ranges::forward_range<test_forward_range<int>> );
+static_assert( ! std::ranges::forward_range<test_input_range<int>> );
+static_assert( ! std::ranges::forward_range<test_output_range<int>> );
+
+static_assert( std::ranges::bidirectional_range<test_contiguous_range<int>> );
+static_assert( std::ranges::bidirectional_range<test_random_access_range<int>>);
+static_assert( std::ranges::bidirectional_range<test_bidirectional_range<int>>);
+static_assert( ! std::ranges::bidirectional_range<test_forward_range<int>> );
+static_assert( ! std::ranges::bidirectional_range<test_input_range<int>> );
+static_assert( ! std::ranges::bidirectional_range<test_output_range<int>> );
+
+static_assert( std::ranges::random_access_range<test_contiguous_range<int>> );
+static_assert( std::ranges::random_access_range<test_random_access_range<int>>);
+static_assert( ! std::ranges::random_access_range<test_bidirectional_range<int>>);
+static_assert( ! std::ranges::random_access_range<test_forward_range<int>> );
+static_assert( ! std::ranges::random_access_range<test_input_range<int>> );
+static_assert( ! std::ranges::random_access_range<test_output_range<int>> );
+
+static_assert( std::ranges::contiguous_range<test_contiguous_range<int>> );
+static_assert( ! std::ranges::contiguous_range<test_random_access_range<int>>);
+static_assert( ! std::ranges::contiguous_range<test_bidirectional_range<int>>);
+static_assert( ! std::ranges::contiguous_range<test_forward_range<int>> );
+static_assert( ! std::ranges::contiguous_range<test_input_range<int>> );
+static_assert( ! std::ranges::contiguous_range<test_output_range<int>> );
diff --git a/libstdc++-v3/testsuite/std/ranges/sized.cc b/libstdc++-v3/testsuite/std/ranges/sized.cc
new file mode 100644
index 00000000000..dd685c7a674
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/sized.cc
@@ -0,0 +1,75 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ranges>
+#include <testsuite_iterators.h>
+
+static_assert( std::ranges::sized_range<int(&)[1]> );
+static_assert( std::ranges::sized_range<const int(&)[1]> );
+static_assert( std::ranges::sized_range<int[1]> );
+static_assert( !std::ranges::sized_range<int*> );
+
+using namespace __gnu_test;
+
+// ranges::size(r) uses (end(r) - begin(r))
+static_assert( std::ranges::sized_range<test_contiguous_range<int>> );
+static_assert( std::ranges::sized_range<test_contiguous_range<int>&> );
+static_assert( std::ranges::sized_range<test_random_access_range<int>> );
+static_assert( std::ranges::sized_range<test_random_access_range<int>&> );
+// ranges::size(r) is invalid, (end(r) - begin(r)) requires sized sentinel
+static_assert(!std::ranges::sized_range<test_bidirectional_range<int>> );
+static_assert(!std::ranges::sized_range<test_bidirectional_range<int>&> );
+static_assert(!std::ranges::sized_range<test_forward_range<int>> );
+static_assert(!std::ranges::sized_range<test_forward_range<int>&> );
+static_assert(!std::ranges::sized_range<test_input_range<int>> );
+static_assert(!std::ranges::sized_range<test_input_range<int>&> );
+static_assert(!std::ranges::sized_range<test_output_range<int>> );
+static_assert(!std::ranges::sized_range<test_output_range<int>&> );
+
+// ranges::size(r) uses r.size()
+static_assert( std::ranges::sized_range<test_contiguous_sized_range<int>> );
+static_assert( std::ranges::sized_range<test_contiguous_sized_range<int>&> );
+static_assert( std::ranges::sized_range<test_random_access_sized_range<int>> );
+static_assert( std::ranges::sized_range<test_random_access_sized_range<int>&> );
+static_assert( std::ranges::sized_range<test_bidirectional_sized_range<int>> );
+static_assert( std::ranges::sized_range<test_bidirectional_sized_range<int>&> );
+static_assert( std::ranges::sized_range<test_forward_sized_range<int>> );
+static_assert( std::ranges::sized_range<test_forward_sized_range<int>&> );
+static_assert( std::ranges::sized_range<test_input_sized_range<int>> );
+static_assert( std::ranges::sized_range<test_input_sized_range<int>&> );
+static_assert( std::ranges::sized_range<test_output_sized_range<int>> );
+static_assert( std::ranges::sized_range<test_output_sized_range<int>&> );
+
+using long_range = __gnu_test::test_random_access_sized_range<long>;
+template<> constexpr bool std::ranges::disable_sized_range<long_range> = true;
+
+// Despite being disabled, this is still a sized_range because ranges::size(r)
+// works, by using (ranges::end(r) - ranges::begin(r)).
+static_assert( std::ranges::sized_range<long_range> );
+static_assert( std::ranges::sized_range<long_range&> );
+
+using short_range = __gnu_test::test_bidirectional_sized_range<short>;
+template<> constexpr bool std::ranges::disable_sized_range<short_range> = true;
+
+// This is not a sized range because ranges::size(r) cannot use member size,
+// or ADL size, and (ranges::end(r) - ranges::begin(r)) is ill-formed for
+// bidirectional iterators.
+static_assert( !std::ranges::sized_range<short_range> );
+static_assert( !std::ranges::sized_range<short_range&> );
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index c5ae5b123fe..d20257c1b31 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -95,7 +95,7 @@ namespace __gnu_test
 #if __cplusplus >= 201103L
       template<class U>
       typename std::enable_if<std::is_assignable<T&, U>::value>::type
-      operator=(U&& new_val)
+      operator=(U&& new_val) const
       {
 	ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
 	SharedInfo->writtento[ptr - SharedInfo->first] = 1;
@@ -720,6 +720,25 @@ namespace __gnu_test
       typename Iter<T>::ContainerType bounds;
     };
 
+  template<typename T>
+    using test_contiguous_range
+      = test_range<T, contiguous_iterator_wrapper>;
+  template<typename T>
+    using test_random_access_range
+      = test_range<T, random_access_iterator_wrapper>;
+  template<typename T>
+    using test_bidirectional_range
+      = test_range<T, bidirectional_iterator_wrapper>;
+  template<typename T>
+    using test_forward_range
+      = test_range<T, forward_iterator_wrapper>;
+  template<typename T>
+    using test_input_range
+      = test_range<T, input_iterator_wrapper>;
+  template<typename T>
+    using test_output_range
+      = test_range<T, output_iterator_wrapper>;
+
   // A type meeting the minimum std::sized_range requirements
   template<typename T, template<typename> class Iter>
     struct test_sized_range : test_range<T, Iter>
@@ -729,6 +748,25 @@ namespace __gnu_test
       std::size_t size() const noexcept
       { return this->bounds.size(); }
     };
+
+  template<typename T>
+    using test_contiguous_sized_range
+      = test_sized_range<T, contiguous_iterator_wrapper>;
+  template<typename T>
+    using test_random_access_sized_range
+      = test_sized_range<T, random_access_iterator_wrapper>;
+  template<typename T>
+    using test_bidirectional_sized_range
+      = test_sized_range<T, bidirectional_iterator_wrapper>;
+  template<typename T>
+    using test_forward_sized_range
+      = test_sized_range<T, forward_iterator_wrapper>;
+  template<typename T>
+    using test_input_sized_range
+      = test_sized_range<T, input_iterator_wrapper>;
+  template<typename T>
+    using test_output_sized_range
+      = test_sized_range<T, output_iterator_wrapper>;
 #endif // C++20
 } // namespace __gnu_test
 #endif // _TESTSUITE_ITERATORS


More information about the Gcc-patches mailing list