On Wed, 26 Mar 2025 at 07:26, Tomasz Kamiński <tkami...@redhat.com> wrote: > > As pointed out by Hewill Kang (reporter) in the issue, checking if iterator > of the incoming range satisfies __cpp17_input_iterator, may still lead > to hard errors inside of insert_range for iterators that satisfies > that concept, but specialize iterator_traits without iterator_category > typedef (std::common_iterator specialize iterator_traits without > iterator_category in some cases). > > To address that we instead check if the iterator_traits<It>::iterator_category > is present and denote at least input_iterator_tag, using existing > __has_input_iter_cat. > > PR libstdc++/119415 > > libstdc++-v3/ChangeLog: > > * include/std/flat_set (_Flat_set_impl:insert_range): > Replace __detail::__cpp17_input_iterator with __has_input_iter_cat. > * testsuite/23_containers/flat_multiset/1.cc: New tests > * testsuite/23_containers/flat_set/1.cc: New tests > --- > Tested on x86_64-linux. OK for trunk?
OK thanks > libstdc++-v3/include/std/flat_set | 2 +- > .../23_containers/flat_multiset/1.cc | 57 +++++++++++++++++-- > .../testsuite/23_containers/flat_set/1.cc | 57 +++++++++++++++++-- > 3 files changed, 103 insertions(+), 13 deletions(-) > > diff --git a/libstdc++-v3/include/std/flat_set > b/libstdc++-v3/include/std/flat_set > index bab56742ddd..a7b0b8aef15 100644 > --- a/libstdc++-v3/include/std/flat_set > +++ b/libstdc++-v3/include/std/flat_set > @@ -481,7 +481,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > if constexpr (requires { _M_cont.insert_range(_M_cont.end(), __rg); > }) > __it = _M_cont.insert_range(_M_cont.end(), __rg); > else if constexpr (ranges::common_range<_Rg> > - && > __detail::__cpp17_input_iterator<ranges::iterator_t<_Rg>>) > + && __has_input_iter_cat<ranges::iterator_t<_Rg>>) > __it = _M_cont.insert(_M_cont.end(), ranges::begin(__rg), > ranges::end(__rg)); > else > { > diff --git a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc > b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc > index cc31164315a..dc3cecd9720 100644 > --- a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc > +++ b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc > @@ -152,19 +152,64 @@ struct NoInsertRange : std::vector<T> > void insert_range(typename std::vector<T>::const_iterator, R&&) = delete; > }; > > +struct NoCatIterator { > + using difference_type = int; > + using value_type = int; > + > + NoCatIterator() : v(0) {} > + NoCatIterator(int x) : v(x) {} > + > + int operator*() const > + { return v; } > + > + NoCatIterator& operator++() > + { > + ++v; > + return *this; > + } > + > + NoCatIterator operator++(int) > + { > + ++v; > + return NoCatIterator(v-1); > + } > + > + bool operator==(const NoCatIterator& rhs) const > + { return v == rhs.v; } > + > +private: > + int v; > +}; > + > +template<> > +struct std::iterator_traits<NoCatIterator> { > + using difference_type = int; > + using value_type = int; > + using iterator_concept = std::input_iterator_tag; > + // no iterator_category, happens also for common_iterator > +}; > + > void test07() > { > + std::flat_multiset<int> s; > + std::flat_multiset<int, std::less<int>, NoInsertRange<int>> s2; > + > + auto r = std::ranges::subrange<NoCatIterator>(1, 6); > + s.insert_range(r); > + VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); > + s2.insert_range(r); > + VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); > + > #ifdef __SIZEOF_INT128__ > // PR libstdc++/119415 - flat_foo::insert_range cannot handle common ranges > // on c++20 only iterators > - auto r = std::views::iota(__int128(1), __int128(6)); > - > - std::flat_multiset<int> s; > - s.insert_range(r); > + auto r2 = std::views::iota(__int128(1), __int128(6)); > + s.clear(); > + s.insert_range(r2); > VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); > > - std::flat_multiset<int, std::less<int>, NoInsertRange<int>> s2; > - s2.insert_range(r); > + s2.clear(); > + s2.insert_range(r2); > VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); > #endif > } > diff --git a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc > b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc > index 16881d788fc..90f5855859f 100644 > --- a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc > +++ b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc > @@ -167,19 +167,64 @@ struct NoInsertRange : std::vector<T> > void insert_range(typename std::vector<T>::const_iterator, R&&) = delete; > }; > > +struct NoCatIterator { > + using difference_type = int; > + using value_type = int; > + > + NoCatIterator() : v(0) {} > + NoCatIterator(int x) : v(x) {} > + > + int operator*() const > + { return v; } > + > + NoCatIterator& operator++() > + { > + ++v; > + return *this; > + } > + > + NoCatIterator operator++(int) > + { > + ++v; > + return NoCatIterator(v-1); > + } > + > + bool operator==(const NoCatIterator& rhs) const > + { return v == rhs.v; } > + > +private: > + int v; > +}; > + > +template<> > +struct std::iterator_traits<NoCatIterator> { > + using difference_type = int; > + using value_type = int; > + using iterator_concept = std::input_iterator_tag; > + // no iterator_category, happens also for common_iterator > +}; > + > void test07() > { > + std::flat_set<int> s; > + std::flat_set<int, std::less<int>, NoInsertRange<int>> s2; > + > + auto r = std::ranges::subrange<NoCatIterator>(1, 6); > + s.insert_range(r); > + VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); > + s2.insert_range(r); > + VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); > + > #ifdef __SIZEOF_INT128__ > // PR libstdc++/119415 - flat_foo::insert_range cannot handle common ranges > // on c++20 only iterators > - auto r = std::views::iota(__int128(1), __int128(6)); > - > - std::flat_set<int> s; > - s.insert_range(r); > + auto r2 = std::views::iota(__int128(1), __int128(6)); > + s.clear(); > + s.insert_range(r2); > VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); > > - std::flat_set<int, std::less<int>, NoInsertRange<int>> s2; > - s2.insert_range(r); > + s2.clear(); > + s2.insert_range(r2); > VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); > #endif > } > -- > 2.48.1 >