diff --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h --- a/libcxx/include/__algorithm/fill_n.h +++ b/libcxx/include/__algorithm/fill_n.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_FILL_N_H #define _LIBCPP___ALGORITHM_FILL_N_H +#include <__algorithm/move.h> #include <__config> #include <__iterator/iterator_traits.h> #include @@ -34,7 +35,7 @@ _OutputIterator fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_) { - return _VSTD::__fill_n(__first, _VSTD::__convert_to_integral(__n), __value_); + return _VSTD::__fill_n(_LIBCPP_MOVE_AFTER_CXX17(__first), _VSTD::__convert_to_integral(__n), __value_); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1081,6 +1081,18 @@ # define _LIBCPP_CONSTEXPR_AFTER_CXX17 #endif +// In C++17 (and earlier) an iterator is required to be CopyConstructible and +// CopyAssignable, but not MoveConstructibe nor MoveAssignable. +// In C++20 the concepts input_iterator and output_iterator require movable but +// not copyable. (forward_iterator requires copyable.) +// Depending on the standard used some algorithms need to be adapted, for +// example fill_n calls __fill_n with an OutputIterator argument. +#if _LIBCPP_STD_VER > 17 +# define _LIBCPP_MOVE_AFTER_CXX17(__obj) _VSTD::move(__obj) +#else +# define _LIBCPP_MOVE_AFTER_CXX17(__obj) __obj +#endif + #if __has_cpp_attribute(nodiscard) || defined(_LIBCPP_COMPILER_MSVC) # define _LIBCPP_NODISCARD [[nodiscard]] #elif defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(_LIBCPP_CXX03_LANG) diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h --- a/libcxx/test/support/test_iterators.h +++ b/libcxx/test/support/test_iterators.h @@ -32,6 +32,14 @@ TEST_CONSTEXPR_CXX14 It base() const {return it_;} TEST_CONSTEXPR_CXX14 output_iterator() {} +#if TEST_STD_VER > 17 + // Starting with C++20 an output_iterator must be movable and doesn't + // require copyable. + output_iterator(const output_iterator&) = delete; + output_iterator(output_iterator&&) = default; + output_iterator& operator=(const output_iterator&) = delete; + output_iterator& operator=(output_iterator&&) = default; +#endif explicit TEST_CONSTEXPR_CXX14 output_iterator(It it) : it_(it) {} template TEST_CONSTEXPR_CXX14 output_iterator(const output_iterator& u) :it_(u.it_) {}