diff --git a/libcxx/include/__iterator/insert_iterator.h b/libcxx/include/__iterator/insert_iterator.h --- a/libcxx/include/__iterator/insert_iterator.h +++ b/libcxx/include/__iterator/insert_iterator.h @@ -14,6 +14,7 @@ #include <__iterator/iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> +#include <__ranges/access.h> #include <__utility/move.h> #include @@ -36,8 +37,12 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP protected: _Container* container; - typename _Container::iterator iter; // FIXME: `ranges::iterator_t` in C++20 mode -public: +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) + ranges::iterator_t<_Container> iter; +#else + typename _Container::iterator iter; +#endif + public: typedef output_iterator_tag iterator_category; typedef void value_type; #if _LIBCPP_STD_VER > 17 @@ -49,8 +54,13 @@ typedef void reference; typedef _Container container_type; +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) + _LIBCPP_INLINE_VISIBILITY constexpr insert_iterator(_Container& __x, ranges::iterator_t<_Container> __i) + : container(_VSTD::addressof(__x)), iter(__i) {} +#else _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator(_Container& __x, typename _Container::iterator __i) : container(_VSTD::addressof(__x)), iter(__i) {} +#endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator& operator=(const typename _Container::value_type& __value_) {iter = container->insert(iter, __value_); ++iter; return *this;} #ifndef _LIBCPP_CXX03_LANG diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp @@ -28,6 +28,7 @@ // typedef void pointer; // }; +#include #include #include #include @@ -70,9 +71,38 @@ #endif } +struct NoIteratorAlias { + long data_[3] = {}; + using value_type = int; + long* begin() { return nullptr; } + constexpr long* insert(long* pos, int value) { + *pos = value; + return pos; + } +}; + +#if TEST_STD_VER > 17 +constexpr bool test_no_iterator_alias() { + NoIteratorAlias c; + auto it = std::insert_iterator(c, c.data_); + *it++ = 1; + *it++ = 2; + assert(c.data_[0] == 1); + assert(c.data_[1] == 2); + assert(c.data_[2] == 0); + return true; +} +#endif + int main(int, char**) { test >(); - return 0; +#if TEST_STD_VER > 17 + test(); + test_no_iterator_alias(); + static_assert(test_no_iterator_alias()); +#endif + + return 0; }