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 { };