These patches are modest reworkings of previous patches.

The patch for char_traits was pretty much approved already.  But in response to 
a comment from François I at least added __copy_backwards, and used ptrdiff_t 
instead of size_t parameters and I put all the mem* wrappers in a __detail 
namespace. I didn't change some names. I know Jonathan wanted a bikeshed 
discussion.

For the constexpr iterators I was asked to simplify the testsuite. Done.

These would finish p1032 except for std::string::copy which I think should wait 
behind the rest of constexpr string.

Another thing I need to do is respond to the SG-10 changes for the p1032 
macros.  There's one thing that bothers me still in light of the policy that 
these macros are names __cpp_lib_constexpr_HEADER: We sill have 
__cpp_lib_constexpr_algorithmS in <algorithm>.

OK if these pass final retesting?
2019-12-10  Edward Smith-Rowland  <3dw...@verizon.net>

	Implement the char_traits and string_view part of C++20 p1032 Misc.
	constexpr bits.
	* include/bits/char_traits.h (move, copy, assign): Constexpr.
	* include/bits/stl_algobase.h (__memcpy, __memset): New.
	* include/ext/pod_char_traits.h (from, to, operator==, operator<)
	(assign, eq, lt, compare, length, find, move, copy, assign)
	(to_char_type, to_int_type, eq_int_type, eof, not_eof):
	Make these constespr for appropriate standards.
	* include/std/string_view (copy): Constexpr.
	* testsuite/21_strings/char_traits/requirements/char/constexpr.cc: New test.
	* testsuite/21_strings/char_traits/requirements/wchar_t/constexpr.cc: New test.
	* testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc: New test.
	* testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc: New test.

Index: include/bits/char_traits.h
===================================================================
--- include/bits/char_traits.h	(revision 279174)
+++ include/bits/char_traits.h	(working copy)
@@ -113,13 +113,13 @@
       static _GLIBCXX14_CONSTEXPR const char_type*
       find(const char_type* __s, std::size_t __n, const char_type& __a);
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, std::size_t __n);
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, std::size_t __n);
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, std::size_t __n, char_type __a);
 
       static _GLIBCXX_CONSTEXPR char_type
@@ -179,18 +179,18 @@
     }
 
   template<typename _CharT>
-    typename char_traits<_CharT>::char_type*
+    _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type*
     char_traits<_CharT>::
     move(char_type* __s1, const char_type* __s2, std::size_t __n)
     {
       if (__n == 0)
 	return __s1;
-      return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
-						    __n * sizeof(char_type)));
+      return static_cast<_CharT*>
+		(std::__detail::__memmove<true>(__s1, __s2, __n));
     }
 
   template<typename _CharT>
-    typename char_traits<_CharT>::char_type*
+    _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type*
     char_traits<_CharT>::
     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
     {
@@ -200,7 +200,7 @@
     }
 
   template<typename _CharT>
-    typename char_traits<_CharT>::char_type*
+    _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type*
     char_traits<_CharT>::
     assign(char_type* __s, std::size_t __n, char_type __a)
     {
@@ -349,28 +349,30 @@
 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
+	return static_cast<char_type*>
+		(std::__detail::__memmove<true>(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
+	return static_cast<char_type*>(
+			std::__detail::__memcpy(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	if (__n == 0)
 	  return __s;
-	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
+	return static_cast<char_type*>(std::__detail::__memset(__s, __a, __n));
       }
 
       static _GLIBCXX_CONSTEXPR char_type
@@ -458,27 +460,45 @@
 	return wmemchr(__s, __a, __n);
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
+#ifdef __cpp_lib_is_constant_evaluated
+	if (std::is_constant_evaluated())
+	  return static_cast<char_type*>
+		   (std::__detail::__memmove<true>(__s1, __s2, __n));
+	else
+#endif
 	return wmemmove(__s1, __s2, __n);
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
+#ifdef __cpp_lib_is_constant_evaluated
+	if (std::is_constant_evaluated())
+	  return static_cast<char_type*>(
+			std::__detail::__memcpy(__s1, __s2, __n));
+	else
+#endif
 	return wmemcpy(__s1, __s2, __n);
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	if (__n == 0)
 	  return __s;
+#ifdef __cpp_lib_is_constant_evaluated
+	if (std::is_constant_evaluated())
+	  return static_cast<char_type*>(
+		std::__detail::__memset(__s, __a, __n));
+	else
+#endif
 	return wmemset(__s, __a, __n);
       }
 
@@ -567,28 +587,30 @@
 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
+	return static_cast<char_type*>
+		(std::__detail::__memmove<true>(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
+	return static_cast<char_type*>(
+			std::__detail::__memcpy(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	if (__n == 0)
 	  return __s;
-	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
+	return static_cast<char_type*>(std::__detail::__memset(__s, __a, __n));
       }
 
       static _GLIBCXX_CONSTEXPR char_type
@@ -680,25 +702,25 @@
 	return 0;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return (static_cast<char_type*>
-		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
+	return static_cast<char_type*>
+		(std::__detail::__memmove<true>(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return (static_cast<char_type*>
-		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
+	return static_cast<char_type*>(
+			std::__detail::__memcpy(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	for (size_t __i = 0; __i < __n; ++__i)
@@ -783,25 +805,25 @@
 	return 0;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
 	return (static_cast<char_type*>
-		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
+		 (std::__detail::__memmove<true>(__s1, __s2, __n)));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       { 
 	if (__n == 0)
 	  return __s1;
-	return (static_cast<char_type*>
-		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
+	return (static_cast<char_type*>(
+			std::__detail::__memcpy(__s1, __s2, __n)));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	for (size_t __i = 0; __i < __n; ++__i)
Index: include/bits/stl_algobase.h
===================================================================
--- include/bits/stl_algobase.h	(revision 279174)
+++ include/bits/stl_algobase.h	(working copy)
@@ -80,19 +80,22 @@
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+namespace __detail
+{
   /*
    * A constexpr wrapper for __builtin_memmove.
+   * When constant-evaluated performs a forward copy.
    * @param __num The number of elements of type _Tp (not bytes).
    */
   template<bool _IsMove, typename _Tp>
     _GLIBCXX14_CONSTEXPR
     inline void*
-    __memmove(_Tp* __dst, const _Tp* __src, size_t __num)
+    __memmove(_Tp* __dst, const _Tp* __src, ptrdiff_t __num)
     {
 #ifdef __cpp_lib_is_constant_evaluated
       if (std::is_constant_evaluated())
 	{
-	  for(; __num > 0; --__num)
+	  for (; __num > 0; --__num)
 	    {
 	      if constexpr (_IsMove)
 		*__dst = std::move(*__src);
@@ -106,10 +109,81 @@
       else
 #endif
 	return __builtin_memmove(__dst, __src, sizeof(_Tp) * __num);
-      return __dst;
     }
 
   /*
+   * A constexpr wrapper for __builtin_memmove.
+   * When constant-evaluated performs a backward copy.
+   * @param __num The number of elements of type _Tp (not bytes).
+   */
+  template<bool _IsMove, typename _Tp>
+    _GLIBCXX14_CONSTEXPR
+    inline void*
+    __copy_backward(_Tp* __dst, const _Tp* __src, ptrdiff_t __num)
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	{
+	  __dst += __num;
+	  __src += __num;
+	  for (; __num != 0; --__num)
+	    {
+	      if constexpr (_IsMove)
+		*--__dst = std::move(*--__src);
+	      else
+		*--__dst = *--__src;
+	    }
+	  return __dst;
+	}
+      else
+#endif
+	return __builtin_memmove(__dst, __src, sizeof(_Tp) * __num);
+    }
+
+  /*
+   * A constexpr wrapper for __builtin_memcpy.
+   * When constant-evaluated performs a forward copy.
+   * @param __num The number of elements of type _Tp (not bytes).
+   */
+  template<typename _Tp>
+    _GLIBCXX14_CONSTEXPR
+    inline void*
+    __memcpy(_Tp* __dst, const _Tp* __src, ptrdiff_t __num)
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	{
+	  for (; __num > 0; --__num)
+	    *__dst++ = *__src++;
+	  return __dst;
+	}
+      else
+#endif
+	return __builtin_memcpy(__dst, __src, sizeof(_Tp) * __num);
+    }
+
+  /*
+   * A constexpr wrapper for __builtin_memset.
+   * @param __num The number of elements of type _Tp (not bytes).
+   */
+  template<typename _Tp>
+    _GLIBCXX14_CONSTEXPR
+    inline void*
+    __memset(_Tp* __dst, _Tp __a, ptrdiff_t __num)
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	{
+	  for (; __num > 0; --__num)
+	    *__dst = __a;
+	  return __dst;
+	}
+      else
+#endif
+	return __builtin_memset(__dst, __a, sizeof(_Tp) * __num);
+    }
+
+  /*
    * A constexpr wrapper for __builtin_memcmp.
    * @param __num The number of elements of type _Tp (not bytes).
    */
@@ -116,12 +190,12 @@
   template<typename _Tp>
     _GLIBCXX14_CONSTEXPR
     inline int
-    __memcmp(const _Tp* __first1, const _Tp* __first2, size_t __num)
+    __memcmp(const _Tp* __first1, const _Tp* __first2, ptrdiff_t __num)
     {
 #ifdef __cpp_lib_is_constant_evaluated
       if (std::is_constant_evaluated())
 	{
-	  for(; __num > 0; ++__first1, ++__first2, --__num)
+	  for (; __num > 0; ++__first1, ++__first2, --__num)
 	    if (*__first1 != *__first2)
 	      return *__first1 < *__first2 ? -1 : 1;
 	  return 0;
@@ -130,6 +204,7 @@
 #endif
 	return __builtin_memcmp(__first1, __first2, sizeof(_Tp) * __num);
     }
+} // namespace __detail
 
 #if __cplusplus < 201103L
   // See http://gcc.gnu.org/ml/libstdc++/2004-08/msg00167.html: in a
@@ -449,7 +524,7 @@
 #endif
 	  const ptrdiff_t _Num = __last - __first;
 	  if (_Num)
-	    std::__memmove<_IsMove>(__result, __first, _Num);
+	    std::__detail::__memmove<_IsMove>(__result, __first, _Num);
 	  return __result + _Num;
 	}
     };
@@ -661,7 +736,7 @@
 #endif
 	  const ptrdiff_t _Num = __last - __first;
 	  if (_Num)
-	    std::__memmove<_IsMove>(__result - _Num, __first, _Num);
+	    std::__detail::__memmove<_IsMove>(__result - _Num, __first, _Num);
 	  return __result - _Num;
 	}
     };
@@ -983,7 +1058,7 @@
 	equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2)
 	{
 	  if (const size_t __len = (__last1 - __first1))
-	    return !std::__memcmp(__first1, __first2, __len);
+	    return !std::__detail::__memcmp(__first1, __first2, __len);
 	  return true;
 	}
     };
@@ -1097,7 +1172,8 @@
 	  const size_t __len1 = __last1 - __first1;
 	  const size_t __len2 = __last2 - __first2;
 	  if (const size_t __len = std::min(__len1, __len2))
-	    if (int __result = std::__memcmp(__first1, __first2, __len))
+	    if (int __result = std::__detail::__memcmp(__first1, __first2,
+							__len))
 	      return __result < 0;
 	  return __len1 < __len2;
 	}
Index: include/ext/pod_char_traits.h
===================================================================
--- include/ext/pod_char_traits.h	(revision 279174)
+++ include/ext/pod_char_traits.h	(working copy)
@@ -56,7 +56,7 @@
       value_type	value;
 
       template<typename V2>
-        static char_type
+        static _GLIBCXX_CONSTEXPR char_type
         from(const V2& v)
         {
 	  char_type ret = { static_cast<value_type>(v) };
@@ -64,7 +64,7 @@
 	}
 
       template<typename V2>
-        static V2
+        static _GLIBCXX_CONSTEXPR V2
         to(const char_type& c)
         {
 	  V2 ret = { static_cast<V2>(c.value) };
@@ -74,13 +74,13 @@
     };
 
   template<typename _Value, typename _Int, typename _St>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator==(const character<_Value, _Int, _St>& lhs,
 	       const character<_Value, _Int, _St>& rhs)
     { return lhs.value == rhs.value; }
 
   template<typename _Value, typename _Int, typename _St>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator<(const character<_Value, _Int, _St>& lhs,
 	      const character<_Value, _Int, _St>& rhs)
     { return lhs.value < rhs.value; }
@@ -102,19 +102,19 @@
       typedef fpos<state_type>				pos_type;
       typedef streamoff					off_type;
 
-      static void
+      static _GLIBCXX14_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2)
       { __c1 = __c2; }
 
-      static bool
+      static _GLIBCXX_CONSTEXPR bool
       eq(const char_type& __c1, const char_type& __c2)
       { return __c1 == __c2; }
 
-      static bool
+      static _GLIBCXX_CONSTEXPR bool
       lt(const char_type& __c1, const char_type& __c2)
       { return __c1 < __c2; }
 
-      static int
+      static _GLIBCXX14_CONSTEXPR int
       compare(const char_type* __s1, const char_type* __s2, size_t __n)
       {
 	for (size_t __i = 0; __i < __n; ++__i)
@@ -123,7 +123,7 @@
 	return 0;
       }
 
-      static size_t
+      static _GLIBCXX14_CONSTEXPR size_t
       length(const char_type* __s)
       {
 	const char_type* __p = __s;
@@ -132,7 +132,7 @@
 	return (__p - __s);
       }
 
-      static const char_type*
+      static _GLIBCXX14_CONSTEXPR const char_type*
       find(const char_type* __s, size_t __n, const char_type& __a)
       {
 	for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p)
@@ -141,7 +141,7 @@
 	return 0;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       { 
 	if (__n == 0)
@@ -150,7 +150,7 @@
 	  (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
@@ -159,7 +159,7 @@
 	return __s1;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	std::fill_n(__s, __n, __a);
@@ -166,19 +166,19 @@
         return __s;
       }
 
-      static char_type
+      static _GLIBCXX_CONSTEXPR char_type
       to_char_type(const int_type& __i)
       { return char_type::template from(__i); }
 
-      static int_type
+      static _GLIBCXX_CONSTEXPR int_type
       to_int_type(const char_type& __c)
       { return char_type::template to<int_type>(__c); }
 
-      static bool
+      static _GLIBCXX_CONSTEXPR bool
       eq_int_type(const int_type& __c1, const int_type& __c2)
       { return __c1 == __c2; }
 
-      static int_type
+      static _GLIBCXX_CONSTEXPR int_type
       eof() 
       {
 	int_type __r = { static_cast<typename __gnu_cxx::__conditional_type
@@ -187,7 +187,7 @@
 	return __r;
       }
 
-      static int_type
+      static _GLIBCXX_CONSTEXPR int_type
       not_eof(const int_type& __c)
       { return eq_int_type(__c, eof()) ? int_type() : __c; }
     };
Index: include/std/string_view
===================================================================
--- include/std/string_view	(revision 279174)
+++ include/std/string_view	(working copy)
@@ -262,6 +262,7 @@
 
       // [string.view.ops], string operations:
 
+      _GLIBCXX20_CONSTEXPR
       size_type
       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
       {
Index: testsuite/21_strings/char_traits/requirements/char/constexpr.cc
===================================================================
--- testsuite/21_strings/char_traits/requirements/char/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/char_traits/requirements/char/constexpr.cc	(working copy)
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// 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/>.
+
+#include <string>
+
+constexpr bool
+test()
+{
+  auto ok = true;
+
+  char casv[8]{"ello, W"};
+
+  char das[8]{};
+  std::char_traits<char>::move(das, casv, 7);
+  std::char_traits<char>::copy(das, casv, 7);
+  std::char_traits<char>::assign(das, 7, 'x');
+
+  return ok;
+}
+
+int
+main()
+{
+  static_assert(test());
+}
Index: testsuite/21_strings/char_traits/requirements/wchar_t/constexpr.cc
===================================================================
--- testsuite/21_strings/char_traits/requirements/wchar_t/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/char_traits/requirements/wchar_t/constexpr.cc	(working copy)
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// 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/>.
+
+#include <string>
+
+constexpr bool
+test()
+{
+  auto ok = true;
+
+  wchar_t cawsv[8]{L"ello, W"};
+
+  wchar_t wdas[8]{};
+  std::char_traits<wchar_t>::move(wdas, cawsv, 7);
+  std::char_traits<wchar_t>::copy(wdas, cawsv, 7);
+  std::char_traits<wchar_t>::assign(wdas, 7, L'x');
+
+  return ok;
+}
+
+int
+main()
+{
+  static_assert(test());
+}
Index: testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc
===================================================================
--- testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc	(working copy)
@@ -0,0 +1,37 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// 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/>.
+
+#include <string_view>
+
+constexpr bool
+test_string_view()
+{
+  auto ok = true;
+
+  constexpr std::string_view sv = "Hello, World!!!";
+  char casv[8]{};
+  sv.copy(casv, 7, 1);
+
+  ok = ok && (casv[0] == 'e');
+
+  return ok;
+}
+
+static_assert(test_string_view());
Index: testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc
===================================================================
--- testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc	(working copy)
@@ -0,0 +1,37 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// 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/>.
+
+#include <string_view>
+
+constexpr bool
+test_string_view()
+{
+  auto ok = true;
+
+  constexpr std::wstring_view wsv = L"Hello, World!!!";
+  wchar_t cawsv[8]{};
+  wsv.copy(cawsv, 7, 1);
+
+  ok = ok && (cawsv[0] == L'e');
+
+  return ok;
+}
+
+static_assert(test_string_view());
2019-12-10  Edward Smith-Rowland  <3dw...@verizon.net>

	Implement the <iterator> part of C++20 p1032 Misc constexpr bits.
	* include/bits/stl_iterator.h (back_insert_iterator, back_inserter)
	(front_insert_iterator, front_inserter, insert_iterator, inserter):
	Make constexpr.
	* testsuite/24_iterators/insert_iterator/requirements/constexpr.cc: New.
	* testsuite/24_iterators/back_insert_iterator/requirements/
	constexpr.cc: New.
	* testsuite/24_iterators/front_insert_iterator/requirements/
	constexpr.cc: New.
	* testsuite/24_iterators/headers/iterator/synopsis_c++17.cc: Make test
	C++17 only and block insert_iterator tests for C++17 (because of include
	of synopsis_c++20.cc.
	* testsuite/24_iterators/headers/iterator/synopsis_c++20.cc: Add
	constexpr inserter tests.

Index: include/bits/stl_iterator.h
===================================================================
--- include/bits/stl_iterator.h	(revision 279174)
+++ include/bits/stl_iterator.h	(working copy)
@@ -502,8 +502,12 @@
       /// A nested typedef for the type of whatever container you used.
       typedef _Container          container_type;
 
+#if __cplusplus > 201703L
+      constexpr back_insert_iterator() noexcept = default;
+#endif
+
       /// The only way to create this %iterator is with a container.
-      explicit
+      explicit _GLIBCXX20_CONSTEXPR
       back_insert_iterator(_Container& __x)
       : container(std::__addressof(__x)) { }
 
@@ -526,7 +530,7 @@
 	return *this;
       }
 #else
-      back_insert_iterator&
+      _GLIBCXX20_CONSTEXPR back_insert_iterator&
       operator=(const typename _Container::value_type& __value)
       {
 	container->push_back(__value);
@@ -533,7 +537,7 @@
 	return *this;
       }
 
-      back_insert_iterator&
+      _GLIBCXX20_CONSTEXPR back_insert_iterator&
       operator=(typename _Container::value_type&& __value)
       {
 	container->push_back(std::move(__value));
@@ -542,17 +546,17 @@
 #endif
 
       /// Simply returns *this.
-      back_insert_iterator&
+      _GLIBCXX20_CONSTEXPR back_insert_iterator&
       operator*()
       { return *this; }
 
       /// Simply returns *this.  (This %iterator does not @a move.)
-      back_insert_iterator&
+      _GLIBCXX20_CONSTEXPR back_insert_iterator&
       operator++()
       { return *this; }
 
       /// Simply returns *this.  (This %iterator does not @a move.)
-      back_insert_iterator
+      _GLIBCXX20_CONSTEXPR back_insert_iterator
       operator++(int)
       { return *this; }
     };
@@ -569,7 +573,7 @@
    *  types for you.
   */
   template<typename _Container>
-    inline back_insert_iterator<_Container>
+    inline _GLIBCXX20_CONSTEXPR back_insert_iterator<_Container>
     back_inserter(_Container& __x)
     { return back_insert_iterator<_Container>(__x); }
 
@@ -594,8 +598,13 @@
       /// A nested typedef for the type of whatever container you used.
       typedef _Container          container_type;
 
+#if __cplusplus > 201703L
+      constexpr front_insert_iterator() noexcept = default;
+#endif
+
       /// The only way to create this %iterator is with a container.
-      explicit front_insert_iterator(_Container& __x)
+      explicit _GLIBCXX20_CONSTEXPR
+      front_insert_iterator(_Container& __x)
       : container(std::__addressof(__x)) { }
 
       /**
@@ -617,14 +626,13 @@
 	return *this;
       }
 #else
-      front_insert_iterator&
+      _GLIBCXX20_CONSTEXPR front_insert_iterator&
       operator=(const typename _Container::value_type& __value)
       {
 	container->push_front(__value);
 	return *this;
       }
-
-      front_insert_iterator&
+      _GLIBCXX20_CONSTEXPR front_insert_iterator&
       operator=(typename _Container::value_type&& __value)
       {
 	container->push_front(std::move(__value));
@@ -633,17 +641,17 @@
 #endif
 
       /// Simply returns *this.
-      front_insert_iterator&
+      _GLIBCXX20_CONSTEXPR front_insert_iterator&
       operator*()
       { return *this; }
 
       /// Simply returns *this.  (This %iterator does not @a move.)
-      front_insert_iterator&
+      _GLIBCXX20_CONSTEXPR front_insert_iterator&
       operator++()
       { return *this; }
 
       /// Simply returns *this.  (This %iterator does not @a move.)
-      front_insert_iterator
+      _GLIBCXX20_CONSTEXPR front_insert_iterator
       operator++(int)
       { return *this; }
     };
@@ -660,7 +668,7 @@
    *  types for you.
   */
   template<typename _Container>
-    inline front_insert_iterator<_Container>
+    inline _GLIBCXX20_CONSTEXPR front_insert_iterator<_Container>
     front_inserter(_Container& __x)
     { return front_insert_iterator<_Container>(__x); }
 
@@ -690,10 +698,15 @@
       /// A nested typedef for the type of whatever container you used.
       typedef _Container          container_type;
 
+#if __cplusplus > 201703L
+      constexpr insert_iterator() = default;
+#endif
+
       /**
        *  The only way to create this %iterator is with a container and an
        *  initial position (a normal %iterator into the container).
       */
+      _GLIBCXX20_CONSTEXPR
       insert_iterator(_Container& __x, typename _Container::iterator __i)
       : container(std::__addressof(__x)), iter(__i) {}
 
@@ -729,7 +742,7 @@
 	return *this;
       }
 #else
-      insert_iterator&
+      _GLIBCXX20_CONSTEXPR insert_iterator&
       operator=(const typename _Container::value_type& __value)
       {
 	iter = container->insert(iter, __value);
@@ -737,7 +750,7 @@
 	return *this;
       }
 
-      insert_iterator&
+      _GLIBCXX20_CONSTEXPR insert_iterator&
       operator=(typename _Container::value_type&& __value)
       {
 	iter = container->insert(iter, std::move(__value));
@@ -747,17 +760,17 @@
 #endif
 
       /// Simply returns *this.
-      insert_iterator&
+      _GLIBCXX20_CONSTEXPR insert_iterator&
       operator*()
       { return *this; }
 
       /// Simply returns *this.  (This %iterator does not @a move.)
-      insert_iterator&
+      _GLIBCXX20_CONSTEXPR insert_iterator&
       operator++()
       { return *this; }
 
       /// Simply returns *this.  (This %iterator does not @a move.)
-      insert_iterator&
+      _GLIBCXX20_CONSTEXPR insert_iterator&
       operator++(int)
       { return *this; }
     };
@@ -775,7 +788,7 @@
    *  types for you.
   */
   template<typename _Container, typename _Iterator>
-    inline insert_iterator<_Container>
+    inline _GLIBCXX20_CONSTEXPR insert_iterator<_Container>
     inserter(_Container& __x, _Iterator __i)
     {
       return insert_iterator<_Container>(__x,
Index: testsuite/24_iterators/back_insert_iterator/requirements/constexpr.cc
===================================================================
--- testsuite/24_iterators/back_insert_iterator/requirements/constexpr.cc	(nonexistent)
+++ testsuite/24_iterators/back_insert_iterator/requirements/constexpr.cc	(working copy)
@@ -0,0 +1,67 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// 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/>.
+
+#include <iterator>
+#include <array>
+
+template<typename Tp>
+  struct listoid
+  {
+    using value_type = Tp;
+    using iterator = size_t;
+
+    constexpr listoid() = default;
+
+    constexpr void push_back(const value_type& value) { return; }
+    constexpr void push_back(value_type&& value) { return; }
+    constexpr void push_front(const value_type& value) { return; }
+    constexpr void push_front(value_type&& value) { return; }
+    constexpr iterator insert(iterator pos, const value_type& value) { return pos; }
+    constexpr iterator begin() noexcept { return _M_begin; }
+    constexpr iterator end() noexcept { return _M_end; }
+
+  private:
+    size_t _M_begin = 0;
+    size_t _M_end = 0;
+  };
+
+constexpr bool
+test()
+{
+  listoid<int> l;
+
+  auto ok = true;
+  const int route = 66;
+
+  constexpr std::array<int, 2> b{89, 99};
+  const std::back_insert_iterator<listoid<int>> bi(l);
+  std::copy(b.begin(), b.end(), bi);
+  auto nbi = std::back_inserter(l);
+  nbi = route;
+  nbi = 77;
+
+  return ok;
+}
+
+int
+main()
+{
+  static_assert(test());
+}
Index: testsuite/24_iterators/insert_iterator/requirements/constexpr.cc
===================================================================
--- testsuite/24_iterators/insert_iterator/requirements/constexpr.cc	(nonexistent)
+++ testsuite/24_iterators/insert_iterator/requirements/constexpr.cc	(working copy)
@@ -0,0 +1,68 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// 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/>.
+
+#include <iterator>
+#include <array>
+
+template<typename Tp>
+  struct listoid
+  {
+    using value_type = Tp;
+    using iterator = size_t;
+
+    constexpr listoid() = default;
+
+    constexpr void push_back(const value_type& value) { return; }
+    constexpr void push_back(value_type&& value) { return; }
+    constexpr void push_front(const value_type& value) { return; }
+    constexpr void push_front(value_type&& value) { return; }
+    constexpr iterator insert(iterator pos, const value_type& value) { return pos; }
+    constexpr iterator begin() noexcept { return _M_begin; }
+    constexpr iterator end() noexcept { return _M_end; }
+
+  private:
+    size_t _M_begin = 0;
+    size_t _M_end = 0;
+  };
+
+constexpr bool
+test()
+{
+  listoid<int> l;
+
+  auto ok = true;
+  const int route = 66;
+
+  constexpr std::array<int, 5> a{1, 2, 3, 4, 5};
+  const auto liter = l.begin() + 1;
+  const std::insert_iterator<listoid<int>> ii(l, liter);
+  std::copy(a.begin(), a.end(), ii);
+  auto nii = std::inserter(l, liter);
+  nii = route;
+  nii = 77;
+
+  return ok;
+}
+
+int
+main()
+{
+  static_assert(test());
+}
Index: testsuite/24_iterators/front_insert_iterator/requirements/constexpr.cc
===================================================================
--- testsuite/24_iterators/front_insert_iterator/requirements/constexpr.cc	(nonexistent)
+++ testsuite/24_iterators/front_insert_iterator/requirements/constexpr.cc	(working copy)
@@ -0,0 +1,67 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// 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/>.
+
+#include <iterator>
+#include <array>
+
+template<typename Tp>
+  struct listoid
+  {
+    using value_type = Tp;
+    using iterator = size_t;
+
+    constexpr listoid() = default;
+
+    constexpr void push_back(const value_type& value) { return; }
+    constexpr void push_back(value_type&& value) { return; }
+    constexpr void push_front(const value_type& value) { return; }
+    constexpr void push_front(value_type&& value) { return; }
+    constexpr iterator insert(iterator pos, const value_type& value) { return pos; }
+    constexpr iterator begin() noexcept { return _M_begin; }
+    constexpr iterator end() noexcept { return _M_end; }
+
+  private:
+    size_t _M_begin = 0;
+    size_t _M_end = 0;
+  };
+
+constexpr bool
+test()
+{
+  listoid<int> l;
+
+  auto ok = true;
+  const int route = 66;
+
+  constexpr std::array<int, 2> f{-1, 0};
+  const std::front_insert_iterator<listoid<int>> fi(l);
+  std::copy(f.begin(), f.end(), fi);
+  auto nfi = std::front_inserter(l);
+  nfi = route;
+  nfi = 77;
+
+  return ok;
+}
+
+int
+main()
+{
+  static_assert(test());
+}
Index: testsuite/24_iterators/headers/iterator/synopsis_c++17.cc
===================================================================
--- testsuite/24_iterators/headers/iterator/synopsis_c++17.cc	(revision 279174)
+++ testsuite/24_iterators/headers/iterator/synopsis_c++17.cc	(working copy)
@@ -1,5 +1,5 @@
 // { dg-options "-std=gnu++17" }
-// { dg-do compile }
+// { dg-do compile { target c++17_only } }
 // { dg-require-normal-namespace "" }
 
 // Copyright (C) 2016-2019 Free Software Foundation, Inc.
@@ -88,7 +88,7 @@
 
   template <class Iterator>
   constexpr reverse_iterator<Iterator> make_reverse_iterator(const Iterator&);
-
+#if __cplusplus == 201703L
   template <class Container> class back_insert_iterator;
 
   template <class Container>
@@ -103,7 +103,7 @@
 
   template <class Container, class Iterator>
   insert_iterator<Container> inserter(Container& x, Iterator i);
-
+#endif
   template <class Iterator> class move_iterator;
 
   template <class Iterator1, class Iterator2>
Index: testsuite/24_iterators/headers/iterator/synopsis_c++20.cc
===================================================================
--- testsuite/24_iterators/headers/iterator/synopsis_c++20.cc	(revision 279174)
+++ testsuite/24_iterators/headers/iterator/synopsis_c++20.cc	(working copy)
@@ -76,6 +76,21 @@
     struct iterator_traits<counted_iterator<I>>;
 
   struct unreachable_sentinel_t;
+
+  template <class Container> class back_insert_iterator;
+
+  template <class Container>
+  constexpr back_insert_iterator<Container> back_inserter(Container& x);
+
+  template <class Container> class front_insert_iterator;
+
+  template <class Container>
+  constexpr front_insert_iterator<Container> front_inserter(Container& x);
+
+  template <class Container> class insert_iterator;
+
+  template <class Container, class Iterator>
+  constexpr insert_iterator<Container> inserter(Container& x, Iterator i);
 }
 
 struct I { };

Reply via email to