* [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator @ 2020-02-24 13:29 Patrick Palka 2020-02-24 13:37 ` Patrick Palka 2020-02-24 13:43 ` Jonathan Wakely 0 siblings, 2 replies; 6+ messages in thread From: Patrick Palka @ 2020-02-24 13:29 UTC (permalink / raw) To: gcc-patches; +Cc: libstdc++, jwakely, Patrick Palka This adds some missing pieces of the Ranges TS that make back_insert_iterator and front_insert_iterator conform to the new output_iterator requirements. It also fixes a bug in ranges::__copy_or_move and ranges::__copy_or_move_backward in which we were inspecting the iter_value_t of the output iterator, but iterators such as back_insert_iterator and front_insert_iterator whose value_type is defined to be void do not have an iter_value_t according to [readable.traits] p4. The entire __use_memmove condition can probably be refactored, but the simplest fix for now is to inspect the iterator_traits of the output iterator instead. libstdc++-v3/ChangeLog: PR libstdc++/93884 * include/bits/ranges_algobase.h (__copy_or_move, __copy_or_move_backward): Don't inspect the iter_value_t of the output iterator, instead inspect its iterator_traits directly. * include/bits/stl_iterator.h (back_insert_iterator::container): Conditionally initialize. (back_insert_iterator::difference_type): Conditionally define. (back_insert_iterator::back_insert_iterator): Conditionally define this default constructor. (front_insert_iterator::container): Conditionally initialize. (front_insert_iterator::difference_type): Conditionally define. (front_insert_iterator::front_insert_iterator): Conditionally define this default constructor. --- libstdc++-v3/include/bits/ranges_algobase.h | 4 +- libstdc++-v3/include/bits/stl_iterator.h | 22 ++++++++++ .../back_insert_iterator/pr93884.C | 44 +++++++++++++++++++ .../front_insert_iterator/pr93884.C | 44 +++++++++++++++++++ 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C create mode 100644 libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index 807822e99c8..739424e1a2d 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -249,7 +249,7 @@ namespace ranges else if constexpr (sized_sentinel_for<_Sent, _Iter>) { using _ValueTypeI = iter_value_t<_Iter>; - using _ValueTypeO = iter_value_t<_Out>; + using _ValueTypeO = iterator_traits<_Out>::value_type; constexpr bool __use_memmove = (is_trivially_copyable_v<_ValueTypeI> && is_same_v<_ValueTypeI, _ValueTypeO> @@ -386,7 +386,7 @@ namespace ranges else if constexpr (sized_sentinel_for<_Sent, _Iter>) { using _ValueTypeI = iter_value_t<_Iter>; - using _ValueTypeO = iter_value_t<_Out>; + using _ValueTypeO = iterator_traits<_Out>::value_type; constexpr bool __use_memmove = (is_trivially_copyable_v<_ValueTypeI> && is_same_v<_ValueTypeI, _ValueTypeO> diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 372df223113..0f2742ae4cf 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -496,11 +496,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public iterator<output_iterator_tag, void, void, void, void> { protected: +#if __cplusplus > 201703L + _Container* container = nullptr; +#else _Container* container; +#endif public: /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; +#endif + +#if __cplusplus > 201703L + constexpr back_insert_iterator() noexcept = default; +#endif /// The only way to create this %iterator is with a container. explicit @@ -588,11 +599,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public iterator<output_iterator_tag, void, void, void, void> { protected: +#if __cplusplus <= 201703L _Container* container; +#else + _Container* container = nullptr; +#endif public: /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; +#endif + +#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) diff --git a/libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C b/libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C new file mode 100644 index 00000000000..5a6287ddd40 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C @@ -0,0 +1,44 @@ +// Copyright (C) 2020 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 run { target c++2a } } + +#include <iterator> +#include <algorithm> +#include <vector> +#include <testsuite_hooks.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +void +test01() +{ + auto v = std::vector<int>{}; + auto i = views::iota(0, 10); + auto o = std::back_inserter(v); + static_assert(std::output_iterator<decltype(o), int>); + ranges::copy(i, o); + VERIFY( ranges::equal(v, i) ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C b/libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C new file mode 100644 index 00000000000..ee3d9ac4ed9 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C @@ -0,0 +1,44 @@ +// Copyright (C) 2020 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 run { target c++2a } } + +#include <iterator> +#include <algorithm> +#include <deque> +#include <testsuite_hooks.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +void +test01() +{ + auto v = std::deque<int>{}; + auto i = views::iota(0, 10); + auto o = std::front_inserter(v); + static_assert(std::output_iterator<decltype(o), int>); + ranges::copy(i, std::front_inserter(v)); + VERIFY( ranges::equal(v | views::reverse, i) ); +} + +int +main() +{ + test01(); +} -- 2.25.1.291.ge68e29171c ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator 2020-02-24 13:29 [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator Patrick Palka @ 2020-02-24 13:37 ` Patrick Palka 2020-02-24 13:43 ` Jonathan Wakely 1 sibling, 0 replies; 6+ messages in thread From: Patrick Palka @ 2020-02-24 13:37 UTC (permalink / raw) To: Patrick Palka; +Cc: gcc-patches, libstdc++, jwakely ZOn Mon, 24 Feb 2020, Patrick Palka wrote: > This adds some missing pieces of the Ranges TS that make back_insert_iterator and > front_insert_iterator conform to the new output_iterator requirements. > > It also fixes a bug in ranges::__copy_or_move and > ranges::__copy_or_move_backward in which we were inspecting the iter_value_t of > the output iterator, but iterators such as back_insert_iterator and > front_insert_iterator whose value_type is defined to be void do not have an > iter_value_t according to [readable.traits] p4. The entire __use_memmove > condition can probably be refactored, but the simplest fix for now is to inspect > the iterator_traits of the output iterator instead. > > libstdc++-v3/ChangeLog: > > PR libstdc++/93884 > * include/bits/ranges_algobase.h (__copy_or_move, > __copy_or_move_backward): Don't inspect the iter_value_t of the output > iterator, instead inspect its iterator_traits directly. > * include/bits/stl_iterator.h (back_insert_iterator::container): > Conditionally initialize. > (back_insert_iterator::difference_type): Conditionally define. > (back_insert_iterator::back_insert_iterator): Conditionally define this > default constructor. > (front_insert_iterator::container): Conditionally initialize. > (front_insert_iterator::difference_type): Conditionally define. > (front_insert_iterator::front_insert_iterator): Conditionally define > this default constructor. > --- > libstdc++-v3/include/bits/ranges_algobase.h | 4 +- > libstdc++-v3/include/bits/stl_iterator.h | 22 ++++++++++ > .../back_insert_iterator/pr93884.C | 44 +++++++++++++++++++ > .../front_insert_iterator/pr93884.C | 44 +++++++++++++++++++ > 4 files changed, 112 insertions(+), 2 deletions(-) > create mode 100644 libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C > create mode 100644 libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C > > diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h > index 807822e99c8..739424e1a2d 100644 > --- a/libstdc++-v3/include/bits/ranges_algobase.h > +++ b/libstdc++-v3/include/bits/ranges_algobase.h > @@ -249,7 +249,7 @@ namespace ranges > else if constexpr (sized_sentinel_for<_Sent, _Iter>) > { > using _ValueTypeI = iter_value_t<_Iter>; > - using _ValueTypeO = iter_value_t<_Out>; > + using _ValueTypeO = iterator_traits<_Out>::value_type; > constexpr bool __use_memmove > = (is_trivially_copyable_v<_ValueTypeI> > && is_same_v<_ValueTypeI, _ValueTypeO> > @@ -386,7 +386,7 @@ namespace ranges > else if constexpr (sized_sentinel_for<_Sent, _Iter>) > { > using _ValueTypeI = iter_value_t<_Iter>; > - using _ValueTypeO = iter_value_t<_Out>; > + using _ValueTypeO = iterator_traits<_Out>::value_type; > constexpr bool __use_memmove > = (is_trivially_copyable_v<_ValueTypeI> > && is_same_v<_ValueTypeI, _ValueTypeO> > diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h > index 372df223113..0f2742ae4cf 100644 > --- a/libstdc++-v3/include/bits/stl_iterator.h > +++ b/libstdc++-v3/include/bits/stl_iterator.h > @@ -496,11 +496,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > : public iterator<output_iterator_tag, void, void, void, void> > { > protected: > +#if __cplusplus > 201703L > + _Container* container = nullptr; > +#else > _Container* container; > +#endif Just noticed the order of this conditional is inconsistent with ... > > public: > /// A nested typedef for the type of whatever container you used. > typedef _Container container_type; > +#if __cplusplus > 201703L > + using difference_type = ptrdiff_t; > +#endif > + > +#if __cplusplus > 201703L > + constexpr back_insert_iterator() noexcept = default; > +#endif > > /// The only way to create this %iterator is with a container. > explicit > @@ -588,11 +599,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > : public iterator<output_iterator_tag, void, void, void, void> > { > protected: > +#if __cplusplus <= 201703L > _Container* container; > +#else > + _Container* container = nullptr; > +#endif ... this one. Consider this fixed so that both conditionals are __cplusplus <= 201703L, specifying the pre-C++20 version of the code first. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator 2020-02-24 13:29 [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator Patrick Palka 2020-02-24 13:37 ` Patrick Palka @ 2020-02-24 13:43 ` Jonathan Wakely 2020-02-24 13:53 ` Patrick Palka 1 sibling, 1 reply; 6+ messages in thread From: Jonathan Wakely @ 2020-02-24 13:43 UTC (permalink / raw) To: Patrick Palka; +Cc: gcc-patches, libstdc++ On 24/02/20 08:29 -0500, Patrick Palka wrote: >This adds some missing pieces of the Ranges TS that make back_insert_iterator and >front_insert_iterator conform to the new output_iterator requirements. > >It also fixes a bug in ranges::__copy_or_move and >ranges::__copy_or_move_backward in which we were inspecting the iter_value_t of >the output iterator, but iterators such as back_insert_iterator and >front_insert_iterator whose value_type is defined to be void do not have an >iter_value_t according to [readable.traits] p4. The entire __use_memmove >condition can probably be refactored, but the simplest fix for now is to inspect >the iterator_traits of the output iterator instead. > >libstdc++-v3/ChangeLog: > > PR libstdc++/93884 > * include/bits/ranges_algobase.h (__copy_or_move, > __copy_or_move_backward): Don't inspect the iter_value_t of the output > iterator, instead inspect its iterator_traits directly. > * include/bits/stl_iterator.h (back_insert_iterator::container): > Conditionally initialize. > (back_insert_iterator::difference_type): Conditionally define. > (back_insert_iterator::back_insert_iterator): Conditionally define this > default constructor. > (front_insert_iterator::container): Conditionally initialize. > (front_insert_iterator::difference_type): Conditionally define. > (front_insert_iterator::front_insert_iterator): Conditionally define > this default constructor. >--- > libstdc++-v3/include/bits/ranges_algobase.h | 4 +- > libstdc++-v3/include/bits/stl_iterator.h | 22 ++++++++++ > .../back_insert_iterator/pr93884.C | 44 +++++++++++++++++++ > .../front_insert_iterator/pr93884.C | 44 +++++++++++++++++++ > 4 files changed, 112 insertions(+), 2 deletions(-) > create mode 100644 libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C > create mode 100644 libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C > >diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h >index 807822e99c8..739424e1a2d 100644 >--- a/libstdc++-v3/include/bits/ranges_algobase.h >+++ b/libstdc++-v3/include/bits/ranges_algobase.h >@@ -249,7 +249,7 @@ namespace ranges > else if constexpr (sized_sentinel_for<_Sent, _Iter>) > { > using _ValueTypeI = iter_value_t<_Iter>; >- using _ValueTypeO = iter_value_t<_Out>; >+ using _ValueTypeO = iterator_traits<_Out>::value_type; I think this will fail to compile with Clang, because it needs 'typename' there. > constexpr bool __use_memmove > = (is_trivially_copyable_v<_ValueTypeI> > && is_same_v<_ValueTypeI, _ValueTypeO> >@@ -386,7 +386,7 @@ namespace ranges > else if constexpr (sized_sentinel_for<_Sent, _Iter>) > { > using _ValueTypeI = iter_value_t<_Iter>; >- using _ValueTypeO = iter_value_t<_Out>; >+ using _ValueTypeO = iterator_traits<_Out>::value_type; Same here. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator 2020-02-24 13:43 ` Jonathan Wakely @ 2020-02-24 13:53 ` Patrick Palka 2020-02-24 14:25 ` Jonathan Wakely 0 siblings, 1 reply; 6+ messages in thread From: Patrick Palka @ 2020-02-24 13:53 UTC (permalink / raw) To: Jonathan Wakely; +Cc: Patrick Palka, gcc-patches, libstdc++ On Mon, 24 Feb 2020, Jonathan Wakely wrote: > On 24/02/20 08:29 -0500, Patrick Palka wrote: > > This adds some missing pieces of the Ranges TS that make > > back_insert_iterator and > > front_insert_iterator conform to the new output_iterator requirements. > > > > It also fixes a bug in ranges::__copy_or_move and > > ranges::__copy_or_move_backward in which we were inspecting the iter_value_t > > of > > the output iterator, but iterators such as back_insert_iterator and > > front_insert_iterator whose value_type is defined to be void do not have an > > iter_value_t according to [readable.traits] p4. The entire __use_memmove > > condition can probably be refactored, but the simplest fix for now is to > > inspect > > the iterator_traits of the output iterator instead. > > > > libstdc++-v3/ChangeLog: > > > > PR libstdc++/93884 > > * include/bits/ranges_algobase.h (__copy_or_move, > > __copy_or_move_backward): Don't inspect the iter_value_t of the output > > iterator, instead inspect its iterator_traits directly. > > * include/bits/stl_iterator.h (back_insert_iterator::container): > > Conditionally initialize. > > (back_insert_iterator::difference_type): Conditionally define. > > (back_insert_iterator::back_insert_iterator): Conditionally define > > this > > default constructor. > > (front_insert_iterator::container): Conditionally initialize. > > (front_insert_iterator::difference_type): Conditionally define. > > (front_insert_iterator::front_insert_iterator): Conditionally define > > this default constructor. > > --- > > libstdc++-v3/include/bits/ranges_algobase.h | 4 +- > > libstdc++-v3/include/bits/stl_iterator.h | 22 ++++++++++ > > .../back_insert_iterator/pr93884.C | 44 +++++++++++++++++++ > > .../front_insert_iterator/pr93884.C | 44 +++++++++++++++++++ > > 4 files changed, 112 insertions(+), 2 deletions(-) > > create mode 100644 > > libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C > > create mode 100644 > > libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C > > > > diff --git a/libstdc++-v3/include/bits/ranges_algobase.h > > b/libstdc++-v3/include/bits/ranges_algobase.h > > index 807822e99c8..739424e1a2d 100644 > > --- a/libstdc++-v3/include/bits/ranges_algobase.h > > +++ b/libstdc++-v3/include/bits/ranges_algobase.h > > @@ -249,7 +249,7 @@ namespace ranges > > else if constexpr (sized_sentinel_for<_Sent, _Iter>) > > { > > using _ValueTypeI = iter_value_t<_Iter>; > > - using _ValueTypeO = iter_value_t<_Out>; > > + using _ValueTypeO = iterator_traits<_Out>::value_type; > > I think this will fail to compile with Clang, because it needs > 'typename' there. > > > constexpr bool __use_memmove > > = (is_trivially_copyable_v<_ValueTypeI> > > && is_same_v<_ValueTypeI, _ValueTypeO> > > @@ -386,7 +386,7 @@ namespace ranges > > else if constexpr (sized_sentinel_for<_Sent, _Iter>) > > { > > using _ValueTypeI = iter_value_t<_Iter>; > > - using _ValueTypeO = iter_value_t<_Out>; > > + using _ValueTypeO = iterator_traits<_Out>::value_type; > > Same here. Ah right... Here's v2 of the patch that adds typename to those two aliases and fixes the file extensions on the tests. -- >8 -- libstdc++-v3/ChangeLog: PR libstdc++/93884 * include/bits/ranges_algobase.h (__copy_or_move, __copy_or_move_backward): Don't inspect the iter_value_t of the output iterator, instead inspect its iterator_traits directly. * include/bits/stl_iterator.h (back_insert_iterator::container): Conditionally initialize. (back_insert_iterator::difference_type): Conditionally define. (back_insert_iterator::back_insert_iterator): Conditionally define this default constructor. (front_insert_iterator::container): Conditionally initialize. (front_insert_iterator::difference_type): Conditionally define. (front_insert_iterator::front_insert_iterator): Conditionally define this default constructor. * 24_iterators/back_insert_iterator/pr93884.cc: New test. * 24_iterators/front_insert_iterator/pr93884.cc: New test. --- libstdc++-v3/include/bits/ranges_algobase.h | 4 +- libstdc++-v3/include/bits/stl_iterator.h | 22 ++++++++++ .../back_insert_iterator/pr93884.cc | 44 +++++++++++++++++++ .../front_insert_iterator/pr93884.cc | 44 +++++++++++++++++++ 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.cc create mode 100644 libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.cc diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index 807822e99c8..73f0205ba7f 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -249,7 +249,7 @@ namespace ranges else if constexpr (sized_sentinel_for<_Sent, _Iter>) { using _ValueTypeI = iter_value_t<_Iter>; - using _ValueTypeO = iter_value_t<_Out>; + using _ValueTypeO = typename iterator_traits<_Out>::value_type; constexpr bool __use_memmove = (is_trivially_copyable_v<_ValueTypeI> && is_same_v<_ValueTypeI, _ValueTypeO> @@ -386,7 +386,7 @@ namespace ranges else if constexpr (sized_sentinel_for<_Sent, _Iter>) { using _ValueTypeI = iter_value_t<_Iter>; - using _ValueTypeO = iter_value_t<_Out>; + using _ValueTypeO = typename iterator_traits<_Out>::value_type; constexpr bool __use_memmove = (is_trivially_copyable_v<_ValueTypeI> && is_same_v<_ValueTypeI, _ValueTypeO> diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 372df223113..caaa8c483b8 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -496,11 +496,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public iterator<output_iterator_tag, void, void, void, void> { protected: +#if __cplusplus <= 201703L _Container* container; +#else + _Container* container = nullptr; +#endif public: /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; +#endif + +#if __cplusplus > 201703L + constexpr back_insert_iterator() noexcept = default; +#endif /// The only way to create this %iterator is with a container. explicit @@ -588,11 +599,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public iterator<output_iterator_tag, void, void, void, void> { protected: +#if __cplusplus <= 201703L _Container* container; +#else + _Container* container = nullptr; +#endif public: /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; +#endif + +#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) diff --git a/libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.cc b/libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.cc new file mode 100644 index 00000000000..5a6287ddd40 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2020 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 run { target c++2a } } + +#include <iterator> +#include <algorithm> +#include <vector> +#include <testsuite_hooks.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +void +test01() +{ + auto v = std::vector<int>{}; + auto i = views::iota(0, 10); + auto o = std::back_inserter(v); + static_assert(std::output_iterator<decltype(o), int>); + ranges::copy(i, o); + VERIFY( ranges::equal(v, i) ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.cc b/libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.cc new file mode 100644 index 00000000000..eaf4e9a187f --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2020 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 run { target c++2a } } + +#include <iterator> +#include <algorithm> +#include <deque> +#include <testsuite_hooks.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +void +test01() +{ + auto v = std::deque<int>{}; + auto i = views::iota(0, 10); + auto o = std::front_inserter(v); + static_assert(std::output_iterator<decltype(o), int>); + ranges::copy(i, o); + VERIFY( ranges::equal(v | views::reverse, i) ); +} + +int +main() +{ + test01(); +} -- 2.25.1.291.ge68e29171c ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator 2020-02-24 13:53 ` Patrick Palka @ 2020-02-24 14:25 ` Jonathan Wakely 2020-02-24 17:17 ` Jonathan Wakely 0 siblings, 1 reply; 6+ messages in thread From: Jonathan Wakely @ 2020-02-24 14:25 UTC (permalink / raw) To: Patrick Palka; +Cc: gcc-patches, libstdc++ On 24/02/20 08:53 -0500, Patrick Palka wrote: >On Mon, 24 Feb 2020, Jonathan Wakely wrote: > >> On 24/02/20 08:29 -0500, Patrick Palka wrote: >> > This adds some missing pieces of the Ranges TS that make >> > back_insert_iterator and >> > front_insert_iterator conform to the new output_iterator requirements. >> > >> > It also fixes a bug in ranges::__copy_or_move and >> > ranges::__copy_or_move_backward in which we were inspecting the iter_value_t >> > of >> > the output iterator, but iterators such as back_insert_iterator and >> > front_insert_iterator whose value_type is defined to be void do not have an >> > iter_value_t according to [readable.traits] p4. The entire __use_memmove >> > condition can probably be refactored, but the simplest fix for now is to >> > inspect >> > the iterator_traits of the output iterator instead. >> > >> > libstdc++-v3/ChangeLog: >> > >> > PR libstdc++/93884 >> > * include/bits/ranges_algobase.h (__copy_or_move, >> > __copy_or_move_backward): Don't inspect the iter_value_t of the output >> > iterator, instead inspect its iterator_traits directly. >> > * include/bits/stl_iterator.h (back_insert_iterator::container): >> > Conditionally initialize. >> > (back_insert_iterator::difference_type): Conditionally define. >> > (back_insert_iterator::back_insert_iterator): Conditionally define >> > this >> > default constructor. >> > (front_insert_iterator::container): Conditionally initialize. >> > (front_insert_iterator::difference_type): Conditionally define. >> > (front_insert_iterator::front_insert_iterator): Conditionally define >> > this default constructor. >> > --- >> > libstdc++-v3/include/bits/ranges_algobase.h | 4 +- >> > libstdc++-v3/include/bits/stl_iterator.h | 22 ++++++++++ >> > .../back_insert_iterator/pr93884.C | 44 +++++++++++++++++++ >> > .../front_insert_iterator/pr93884.C | 44 +++++++++++++++++++ >> > 4 files changed, 112 insertions(+), 2 deletions(-) >> > create mode 100644 >> > libstdc++-v3/testsuite/24_iterators/back_insert_iterator/pr93884.C >> > create mode 100644 >> > libstdc++-v3/testsuite/24_iterators/front_insert_iterator/pr93884.C >> > >> > diff --git a/libstdc++-v3/include/bits/ranges_algobase.h >> > b/libstdc++-v3/include/bits/ranges_algobase.h >> > index 807822e99c8..739424e1a2d 100644 >> > --- a/libstdc++-v3/include/bits/ranges_algobase.h >> > +++ b/libstdc++-v3/include/bits/ranges_algobase.h >> > @@ -249,7 +249,7 @@ namespace ranges >> > else if constexpr (sized_sentinel_for<_Sent, _Iter>) >> > { >> > using _ValueTypeI = iter_value_t<_Iter>; >> > - using _ValueTypeO = iter_value_t<_Out>; >> > + using _ValueTypeO = iterator_traits<_Out>::value_type; >> >> I think this will fail to compile with Clang, because it needs >> 'typename' there. >> >> > constexpr bool __use_memmove >> > = (is_trivially_copyable_v<_ValueTypeI> >> > && is_same_v<_ValueTypeI, _ValueTypeO> >> > @@ -386,7 +386,7 @@ namespace ranges >> > else if constexpr (sized_sentinel_for<_Sent, _Iter>) >> > { >> > using _ValueTypeI = iter_value_t<_Iter>; >> > - using _ValueTypeO = iter_value_t<_Out>; >> > + using _ValueTypeO = iterator_traits<_Out>::value_type; >> >> Same here. > >Ah right... Here's v2 of the patch that adds typename to those two >aliases and fixes the file extensions on the tests. OK for master, thanks. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator 2020-02-24 14:25 ` Jonathan Wakely @ 2020-02-24 17:17 ` Jonathan Wakely 0 siblings, 0 replies; 6+ messages in thread From: Jonathan Wakely @ 2020-02-24 17:17 UTC (permalink / raw) To: Patrick Palka; +Cc: gcc-patches, libstdc++ [-- Attachment #1: Type: text/plain, Size: 145 bytes --] This should do the same changes for std::insert_iterator, but it currently crashes the compiler (PR 93907). I am not committing this yet. [-- Attachment #2: patch.txt --] [-- Type: text/x-patch, Size: 11119 bytes --] commit 2db20402125e6136d6768598f5974e917b2622c6 Author: Jonathan Wakely <jwakely@redhat.com> Date: Mon Feb 24 15:50:59 2020 +0000 libstdc++: Add missing bits of P0896R4 pertaining to insert_iterator (PR 93884) This completes the fix for PR 93884. In order to use ranges::iterator_t in std::insert_iterator the definition of ranges::iterator_t and ranges::begin need to be moved, to avoid a circular dependency between <bits/stl_iterator.h> and <bits/range_access.h>. As noted in a FIXME comment, the std::inserter function has the wrong signature because LWG issue 561 was never implemented. That is tracked by PR 93904. PR libstdc++/93884 * include/bits/iterator_concepts.h (__detail::__maybe_borrowed_range) (__cust_access::_Begin, ranges::iterator_t): Move from ... * include/bits/range_access.h: ... here. * include/bits/stl_iterator.h (insert_iterator, inserter): Implement C++20 changes from P0896R4. * testsuite/24_iterators/insert_iterator/pr93884.cc: New test. diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index 08e622259b4..ae0c207d0d9 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -835,6 +835,90 @@ namespace ranges struct default_sentinel_t { }; inline constexpr default_sentinel_t default_sentinel{}; +namespace ranges +{ + template<typename _Tp> + extern const bool enable_borrowed_range; + + namespace __detail + { + // Part of the constraints of ranges::borrowed_range + template<typename _Tp> + concept __maybe_borrowed_range + = is_lvalue_reference_v<_Tp> + || enable_borrowed_range<remove_cvref_t<_Tp>>; + } // namespace __detail + + namespace __cust_access + { + template<typename _Tp> + constexpr decay_t<_Tp> + __decay_copy(_Tp&& __t) + noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) + { return std::forward<_Tp>(__t); } + + template<typename _Tp> + concept __member_begin = requires(_Tp& __t) + { + __t.begin(); + requires input_or_output_iterator<decay_t<decltype(__t.begin())>>; + }; + + void begin(auto&) = delete; + void begin(const auto&) = delete; + + template<typename _Tp> + concept __adl_begin + = std::__detail::__class_or_enum<remove_reference_t<_Tp>> + && requires(_Tp& __t) + { + begin(__t); + requires input_or_output_iterator<decay_t<decltype(begin(__t))>>; + }; + + struct _Begin + { + private: + template<typename _Tp> + static constexpr bool + _S_noexcept() + { + if constexpr (is_array_v<remove_reference_t<_Tp>>) + return true; + else if constexpr (__member_begin<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().begin())); + else + return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); + } + + public: + template<__detail::__maybe_borrowed_range _Tp> + requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp> + || __adl_begin<_Tp> + constexpr auto + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (is_array_v<remove_reference_t<_Tp>>) + { + static_assert(is_lvalue_reference_v<_Tp>); + using _Up = remove_all_extents_t<remove_reference_t<_Tp>>; + static_assert(sizeof(_Up) != 0, "not array of incomplete type"); + return __t + 0; + } + else if constexpr (__member_begin<_Tp>) + return __t.begin(); + else + return begin(__t); + } + }; + } // namespace __cust_access + + template<typename _Tp> + using iterator_t + = decltype(__cust_access::_Begin{}(std::declval<_Tp&>())); + +} // namespace ranges + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // C++20 library concepts diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h index 8b276fd6625..7ae08f58f67 100644 --- a/libstdc++-v3/include/bits/range_access.h +++ b/libstdc++-v3/include/bits/range_access.h @@ -359,13 +359,6 @@ namespace ranges template<typename _Tp, bool _MaxDiff = same_as<_Tp, __max_diff_type>> using __make_unsigned_like_t = conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>; - - // Part of the constraints of ranges::borrowed_range - template<typename _Tp> - concept __maybe_borrowed_range - = is_lvalue_reference_v<_Tp> - || enable_borrowed_range<remove_cvref_t<_Tp>>; - } // namespace __detail namespace __cust_access @@ -373,64 +366,6 @@ namespace ranges using std::ranges::__detail::__maybe_borrowed_range; using std::__detail::__class_or_enum; - template<typename _Tp> - constexpr decay_t<_Tp> - __decay_copy(_Tp&& __t) - noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) - { return std::forward<_Tp>(__t); } - - template<typename _Tp> - concept __member_begin = requires(_Tp& __t) - { - { __decay_copy(__t.begin()) } -> input_or_output_iterator; - }; - - void begin(auto&) = delete; - void begin(const auto&) = delete; - - template<typename _Tp> - concept __adl_begin = __class_or_enum<remove_reference_t<_Tp>> - && requires(_Tp& __t) - { - { __decay_copy(begin(__t)) } -> input_or_output_iterator; - }; - - struct _Begin - { - private: - template<typename _Tp> - static constexpr bool - _S_noexcept() - { - if constexpr (is_array_v<remove_reference_t<_Tp>>) - return true; - else if constexpr (__member_begin<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().begin())); - else - return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); - } - - public: - template<__maybe_borrowed_range _Tp> - requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp> - || __adl_begin<_Tp> - constexpr auto - operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) - { - if constexpr (is_array_v<remove_reference_t<_Tp>>) - { - static_assert(is_lvalue_reference_v<_Tp>); - using _Up = remove_all_extents_t<remove_reference_t<_Tp>>; - static_assert(sizeof(_Up) != 0, "not array of incomplete type"); - return __t + 0; - } - else if constexpr (__member_begin<_Tp>) - return __t.begin(); - else - return begin(__t); - } - }; - template<typename _Tp> concept __member_end = requires(_Tp& __t) { @@ -888,9 +823,6 @@ namespace ranges concept borrowed_range = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>; - template<typename _Tp> - using iterator_t = decltype(ranges::begin(std::declval<_Tp&>())); - template<range _Range> using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index caaa8c483b8..c332343d11b 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -704,19 +704,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class insert_iterator : public iterator<output_iterator_tag, void, void, void, void> { +#if __cplusplus <= 201703L + typedef typename _Container::iterator _Iter; +#else + using _Iter = ranges::iterator_t<_Container>; +#endif + protected: +#if __cplusplus <= 201703L _Container* container; - typename _Container::iterator iter; + _Iter iter; +#else + _Container* container = nullptr; + _Iter iter = _Iter(); +#endif public: /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; + + 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). */ - insert_iterator(_Container& __x, typename _Container::iterator __i) + insert_iterator(_Container& __x, _Iter __i) : container(std::__addressof(__x)), iter(__i) {} /** @@ -782,6 +799,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION insert_iterator& operator++(int) { return *this; } + +#if __cplusplus >= 201703L + template<typename _Cont> + friend insert_iterator<_Cont> + inserter(_Cont&, typename insert_iterator<_Cont>::_Iter); +#endif }; /** @@ -796,6 +819,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * template parameter deduction, making the compiler match the correct * types for you. */ +#if __cplusplus <= 201703L + // FIXME: This version should not exist (PR 93904) template<typename _Container, typename _Iterator> inline insert_iterator<_Container> inserter(_Container& __x, _Iterator __i) @@ -803,6 +828,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return insert_iterator<_Container>(__x, typename _Container::iterator(__i)); } +#else + template<typename _Container> + inline insert_iterator<_Container> + inserter(_Container& __x, typename insert_iterator<_Container>::_Iter __i) + { + return insert_iterator<_Container>(__x, __i); + } +#endif // @} group iterators diff --git a/libstdc++-v3/testsuite/24_iterators/insert_iterator/pr93884.cc b/libstdc++-v3/testsuite/24_iterators/insert_iterator/pr93884.cc new file mode 100644 index 00000000000..e0949e64152 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/insert_iterator/pr93884.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2020 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 run { target c++2a } } + +#include <iterator> +#include <algorithm> +#include <set> +#include <testsuite_hooks.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +void +test01() +{ + auto s = std::set<int>{}; + auto i = views::iota(0, 10); + auto o = std::inserter(s, s.begin()); + static_assert(std::output_iterator<decltype(o), int>); + ranges::copy(i, o); + VERIFY( ranges::equal(s, i) ); +} + +int +main() +{ + test01(); +} ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-02-24 17:17 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-02-24 13:29 [PATCH] libstdc++: Add missing bits of P0896R4 pertaining to [back|front]_insert_iterator Patrick Palka 2020-02-24 13:37 ` Patrick Palka 2020-02-24 13:43 ` Jonathan Wakely 2020-02-24 13:53 ` Patrick Palka 2020-02-24 14:25 ` Jonathan Wakely 2020-02-24 17:17 ` Jonathan Wakely
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).