diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -264,7 +264,7 @@ --------------------------------------------------- ----------------- ``__cpp_lib_polymorphic_allocator`` ``201902L`` --------------------------------------------------- ----------------- - ``__cpp_lib_ranges`` ``202106L`` + ``__cpp_lib_ranges`` ``202207L`` --------------------------------------------------- ----------------- ``__cpp_lib_remove_cvref`` ``201711L`` --------------------------------------------------- ----------------- diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -78,7 +78,7 @@ "`P2465R3 `__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","","" "`P2467R1 `__","LWG","Support exclusive mode for ``fstreams``","July 2022","","" "`P2474R2 `__","LWG","``views::repeat``","July 2022","","","|ranges|" -"`P2494R2 `__","LWG","Relaxing range adaptors to allow for move only types","July 2022","","","|ranges|" +"`P2494R2 `__","LWG","Relaxing range adaptors to allow for move only types","July 2022","|Complete|","17.0","|ranges|" "`P2499R0 `__","LWG","``string_view`` range constructor should be ``explicit``","July 2022","|Complete|","16.0","|ranges|" "`P2502R2 `__","LWG","``std::generator``: Synchronous Coroutine Generator for Ranges","July 2022","","","|ranges|" "`P2508R1 `__","LWG","Exposing ``std::basic-format-string``","July 2022","|Complete|","15.0" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -609,7 +609,6 @@ __ranges/common_view.h __ranges/concepts.h __ranges/container_compatible_range.h - __ranges/copyable_box.h __ranges/counted.h __ranges/dangling.h __ranges/data.h @@ -626,6 +625,7 @@ __ranges/istream_view.h __ranges/join_view.h __ranges/lazy_split_view.h + __ranges/movable_box.h __ranges/non_propagating_cache.h __ranges/owning_view.h __ranges/range_adaptor.h diff --git a/libcxx/include/__ranges/copyable_box.h b/libcxx/include/__ranges/copyable_box.h deleted file mode 100644 --- a/libcxx/include/__ranges/copyable_box.h +++ /dev/null @@ -1,182 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___RANGES_COPYABLE_BOX_H -#define _LIBCPP___RANGES_COPYABLE_BOX_H - -#include <__concepts/constructible.h> -#include <__concepts/copyable.h> -#include <__concepts/movable.h> -#include <__config> -#include <__memory/addressof.h> -#include <__memory/construct_at.h> -#include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if _LIBCPP_STD_VER >= 20 - -// __copyable_box allows turning a type that is copy-constructible (but maybe not copy-assignable) into -// a type that is both copy-constructible and copy-assignable. It does that by introducing an empty state -// and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary -// to handle the case where the copy construction fails after destroying the object. -// -// In some cases, we can completely avoid the use of an empty state; we provide a specialization of -// __copyable_box that does this, see below for the details. - -template -concept __copy_constructible_object = copy_constructible<_Tp> && is_object_v<_Tp>; - -namespace ranges { - // Primary template - uses std::optional and introduces an empty state in case assignment fails. - template<__copy_constructible_object _Tp> - class __copyable_box { - _LIBCPP_NO_UNIQUE_ADDRESS optional<_Tp> __val_; - - public: - template - requires is_constructible_v<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) - noexcept(is_nothrow_constructible_v<_Tp, _Args...>) - : __val_(in_place, std::forward<_Args>(__args)...) - { } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) - requires default_initializable<_Tp> - : __val_(in_place) - { } - - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box const& __other) - noexcept(is_nothrow_copy_constructible_v<_Tp>) - { - if (this != std::addressof(__other)) { - if (__other.__has_value()) __val_.emplace(*__other); - else __val_.reset(); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box&& __other) - noexcept(is_nothrow_move_constructible_v<_Tp>) - { - if (this != std::addressof(__other)) { - if (__other.__has_value()) __val_.emplace(std::move(*__other)); - else __val_.reset(); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; } - - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return __val_.operator->(); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return __val_.operator->(); } - - _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); } - }; - - // This partial specialization implements an optimization for when we know we don't need to store - // an empty state to represent failure to perform an assignment. For copy-assignment, this happens: - // - // 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator - // directly and avoid using std::optional. - // 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as - // destroy-and-then-construct and we know it will never fail, so we don't need an empty state. - // - // The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and - // nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled - // whenever we can apply any of these optimizations for both the copy assignment and the move assignment - // operator. - template - concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>; - - template - concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>; - - template<__copy_constructible_object _Tp> - requires __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp> - class __copyable_box<_Tp> { - _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; - - public: - template - requires is_constructible_v<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) - noexcept(is_nothrow_constructible_v<_Tp, _Args...>) - : __val_(std::forward<_Args>(__args)...) - { } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) - requires default_initializable<_Tp> - : __val_() - { } - - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; - - // Implementation of assignment operators in case we perform optimization (1) - _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box const&) requires copyable<_Tp> = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; - - // Implementation of assignment operators in case we perform optimization (2) - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box const& __other) noexcept { - static_assert(is_nothrow_copy_constructible_v<_Tp>); - if (this != std::addressof(__other)) { - std::destroy_at(std::addressof(__val_)); - std::construct_at(std::addressof(__val_), __other.__val_); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box&& __other) noexcept { - static_assert(is_nothrow_move_constructible_v<_Tp>); - if (this != std::addressof(__other)) { - std::destroy_at(std::addressof(__val_)); - std::construct_at(std::addressof(__val_), std::move(__other.__val_)); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; } - - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return std::addressof(__val_); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return std::addressof(__val_); } - - _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; } - }; -} // namespace ranges - -#endif // _LIBCPP_STD_VER >= 20 - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___RANGES_COPYABLE_BOX_H diff --git a/libcxx/include/__ranges/drop_while_view.h b/libcxx/include/__ranges/drop_while_view.h --- a/libcxx/include/__ranges/drop_while_view.h +++ b/libcxx/include/__ranges/drop_while_view.h @@ -20,8 +20,8 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/movable_box.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> @@ -82,7 +82,7 @@ private: _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; static constexpr bool _UseCache = forward_range<_View>; using _Cache = _If<_UseCache, __non_propagating_cache>, __empty_cache>; diff --git a/libcxx/include/__ranges/filter_view.h b/libcxx/include/__ranges/filter_view.h --- a/libcxx/include/__ranges/filter_view.h +++ b/libcxx/include/__ranges/filter_view.h @@ -28,7 +28,7 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> @@ -53,7 +53,7 @@ requires view<_View> && is_object_v<_Pred> class filter_view : public view_interface> { _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; // We cache the result of begin() to allow providing an amortized O(1) begin() whenever // the underlying range is at least a forward_range. diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -27,8 +27,8 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> #include <__iterator/unreachable_sentinel.h> -#include <__ranges/copyable_box.h> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/movable_box.h> #include <__ranges/view_interface.h> #include <__type_traits/conditional.h> #include <__type_traits/is_nothrow_copy_constructible.h> diff --git a/libcxx/include/__ranges/movable_box.h b/libcxx/include/__ranges/movable_box.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/movable_box.h @@ -0,0 +1,206 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_MOVABLE_BOX_H +#define _LIBCPP___RANGES_MOVABLE_BOX_H + +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__concepts/movable.h> +#include <__config> +#include <__memory/addressof.h> +#include <__memory/construct_at.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +// __movable_box allows turning a type that is move-constructible (but maybe not move-assignable) into +// a type that is both move-constructible and move-assignable. It does that by introducing an empty state +// and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary +// to handle the case where the copy construction fails after destroying the object. +// +// In some cases, we can completely avoid the use of an empty state; we provide a specialization of +// __movable_box that does this, see below for the details. + +// until C++23, `__movable_box` was named `__copyable_box` and required the stored type to be copy-constructible, not +// just move-constructible; we preserve the old behavior in pre-C++23 modes. +template +concept __movable_box_object = +# if _LIBCPP_STD_VER >= 23 + move_constructible<_Tp> +# else + copy_constructible<_Tp> +# endif + && is_object_v<_Tp>; + +namespace ranges { +// Primary template - uses std::optional and introduces an empty state in case assignment fails. +template <__movable_box_object _Tp> +class __movable_box { + _LIBCPP_NO_UNIQUE_ADDRESS optional<_Tp> __val_; + +public: + template + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __movable_box(in_place_t, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Tp, _Args...>) + : __val_(in_place, std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : __val_(in_place) {} + + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box const&) = default; + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box&&) = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& + operator=(__movable_box const& __other) noexcept(is_nothrow_copy_constructible_v<_Tp>) +# if _LIBCPP_STD_VER >= 23 + requires copy_constructible<_Tp> +# endif + { + if (this != std::addressof(__other)) { + if (__other.__has_value()) + __val_.emplace(*__other); + else + __val_.reset(); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box&&) + requires movable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& + operator=(__movable_box&& __other) noexcept(is_nothrow_move_constructible_v<_Tp>) { + if (this != std::addressof(__other)) { + if (__other.__has_value()) + __val_.emplace(std::move(*__other)); + else + __val_.reset(); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { return __val_.operator->(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { return __val_.operator->(); } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); } +}; + +// This partial specialization implements an optimization for when we know we don't need to store +// an empty state to represent failure to perform an assignment. For copy-assignment, this happens: +// +// 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator +// directly and avoid using std::optional. +// 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as +// destroy-and-then-construct and we know it will never fail, so we don't need an empty state. +// +// The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and +// nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled +// whenever we can apply any of these optimizations for both the copy assignment and the move assignment +// operator. + +# if _LIBCPP_STD_VER >= 23 +template +concept __doesnt_need_empty_state = + (copy_constructible<_Tp> + // 1. If copy_constructible is true, movable-box should store only a T if either T models + // copyable, or is_nothrow_move_constructible_v && is_nothrow_copy_constructible_v is true. + ? copyable<_Tp> || (is_nothrow_move_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Tp>) + // 2. Otherwise, movable-box should store only a T if either T models movable or + // is_nothrow_move_constructible_v is true. + : movable<_Tp> || is_nothrow_move_constructible_v<_Tp>); +# else + +template +concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>; + +template +concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>; + +template +concept __doesnt_need_empty_state = __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp>; +# endif + +template <__movable_box_object _Tp> + requires __doesnt_need_empty_state<_Tp> +class __movable_box<_Tp> { + _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; + +public: + template + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __movable_box(in_place_t, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Tp, _Args...>) + : __val_(std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : __val_() {} + + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box const&) = default; + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box&&) = default; + + // Implementation of assignment operators in case we perform optimization (1) + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box const&) + requires copyable<_Tp> + = default; + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box&&) + requires movable<_Tp> + = default; + + // Implementation of assignment operators in case we perform optimization (2) + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& operator=(__movable_box const& __other) noexcept { + static_assert(is_nothrow_copy_constructible_v<_Tp>); + if (this != std::addressof(__other)) { + std::destroy_at(std::addressof(__val_)); + std::construct_at(std::addressof(__val_), __other.__val_); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& operator=(__movable_box&& __other) noexcept { + static_assert(is_nothrow_move_constructible_v<_Tp>); + if (this != std::addressof(__other)) { + std::destroy_at(std::addressof(__val_)); + std::construct_at(std::addressof(__val_), std::move(__other.__val_)); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { return std::addressof(__val_); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { return std::addressof(__val_); } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; } +}; +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_MOVABLE_BOX_H diff --git a/libcxx/include/__ranges/single_view.h b/libcxx/include/__ranges/single_view.h --- a/libcxx/include/__ranges/single_view.h +++ b/libcxx/include/__ranges/single_view.h @@ -12,7 +12,7 @@ #include <__concepts/constructible.h> #include <__config> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> #include <__type_traits/decay.h> @@ -31,48 +31,48 @@ #if _LIBCPP_STD_VER >= 20 namespace ranges { - template - requires is_object_v<_Tp> - class single_view : public view_interface> { - __copyable_box<_Tp> __value_; - - public: - _LIBCPP_HIDE_FROM_ABI - single_view() requires default_initializable<_Tp> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(const _Tp& __t) : __value_(in_place, __t) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(_Tp&& __t) : __value_(in_place, std::move(__t)) {} - - template - requires constructible_from<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(in_place_t, _Args&&... __args) +# if _LIBCPP_STD_VER >= 23 +template +# else +template +# endif + requires is_object_v<_Tp> +class single_view : public view_interface> { + __movable_box<_Tp> __value_; + +public: + _LIBCPP_HIDE_FROM_ABI single_view() + requires default_initializable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(const _Tp& __t) +# if _LIBCPP_STD_VER >= 23 + requires copy_constructible<_Tp> +# endif + : __value_(in_place, __t) { + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(_Tp&& __t) : __value_(in_place, std::move(__t)) {} + + template + requires constructible_from<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(in_place_t, _Args&&... __args) : __value_{in_place, std::forward<_Args>(__args)...} {} - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* begin() noexcept { return data(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* begin() noexcept { return data(); } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* begin() const noexcept { return data(); } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* begin() const noexcept { return data(); } - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* end() noexcept { return data() + 1; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* end() noexcept { return data() + 1; } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* end() const noexcept { return data() + 1; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* end() const noexcept { return data() + 1; } - _LIBCPP_HIDE_FROM_ABI - static constexpr size_t size() noexcept { return 1; } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t size() noexcept { return 1; } - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* data() noexcept { return __value_.operator->(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* data() noexcept { return __value_.operator->(); } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* data() const noexcept { return __value_.operator->(); } - }; + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* data() const noexcept { return __value_.operator->(); } +}; template single_view(_Tp) -> single_view<_Tp>; diff --git a/libcxx/include/__ranges/take_while_view.h b/libcxx/include/__ranges/take_while_view.h --- a/libcxx/include/__ranges/take_while_view.h +++ b/libcxx/include/__ranges/take_while_view.h @@ -20,7 +20,7 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> #include <__type_traits/decay.h> @@ -60,7 +60,7 @@ class __sentinel; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; public: _LIBCPP_HIDE_FROM_ABI take_while_view() diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h --- a/libcxx/include/__ranges/transform_view.h +++ b/libcxx/include/__ranges/transform_view.h @@ -26,8 +26,8 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> #include <__ranges/empty.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> @@ -62,13 +62,17 @@ regular_invocable<_Fn&, range_reference_t<_View>> && __can_reference>>; -template +# if _LIBCPP_STD_VER >= 23 +template +# else +template +# endif requires __transform_view_constraints<_View, _Fn> class transform_view : public view_interface> { template class __iterator; template class __sentinel; - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Fn> __func_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Fn> __func_; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); public: @@ -161,11 +165,14 @@ >; }; -template +# if _LIBCPP_STD_VER >= 23 +template +# else +template +# endif requires __transform_view_constraints<_View, _Fn> -template -class transform_view<_View, _Fn>::__iterator - : public __transform_view_iterator_category_base<_View, _Fn> { +template +class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_category_base<_View, _Fn> { using _Parent = __maybe_const<_Const, transform_view>; using _Base = __maybe_const<_Const, _View>; @@ -357,9 +364,13 @@ } }; -template +# if _LIBCPP_STD_VER >= 23 +template +# else +template +# endif requires __transform_view_constraints<_View, _Fn> -template +template class transform_view<_View, _Fn>::__sentinel { using _Parent = __maybe_const<_Const, transform_view>; using _Base = __maybe_const<_Const, _View>; diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1359,7 +1359,6 @@ module common_view { private header "__ranges/common_view.h" } module concepts { private header "__ranges/concepts.h" } module container_compatible_range { private header "__ranges/container_compatible_range.h" } - module copyable_box { private header "__ranges/copyable_box.h" } module counted { private header "__ranges/counted.h" export span @@ -1382,6 +1381,7 @@ } module join_view { private header "__ranges/join_view.h" } module lazy_split_view { private header "__ranges/lazy_split_view.h" } + module movable_box { private header "__ranges/movable_box.h" } module non_propagating_cache { private header "__ranges/non_propagating_cache.h" } module owning_view { private header "__ranges/owning_view.h" } module range_adaptor { private header "__ranges/range_adaptor.h" } diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -150,7 +150,7 @@ __cpp_lib_parallel_algorithm 201603L __cpp_lib_polymorphic_allocator 201902L __cpp_lib_quoted_string_io 201304L -__cpp_lib_ranges 202106L +__cpp_lib_ranges 202207L __cpp_lib_ranges_as_rvalue 202207L __cpp_lib_ranges_chunk 202202L @@ -381,7 +381,7 @@ # if !defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR) # define __cpp_lib_polymorphic_allocator 201902L # endif -# define __cpp_lib_ranges 202106L +# define __cpp_lib_ranges 202207L # define __cpp_lib_remove_cvref 201711L # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC) # define __cpp_lib_semaphore 201907L diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/properties.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/properties.compile.pass.cpp deleted file mode 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/properties.compile.pass.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -// Test various properties of - -#include - -#include - -#include "types.h" - -template -constexpr bool valid_copyable_box = requires { - typename std::ranges::__copyable_box; -}; - -struct NotCopyConstructible { - NotCopyConstructible() = default; - NotCopyConstructible(NotCopyConstructible&&) = default; - NotCopyConstructible(NotCopyConstructible const&) = delete; - NotCopyConstructible& operator=(NotCopyConstructible&&) = default; - NotCopyConstructible& operator=(NotCopyConstructible const&) = default; -}; - -static_assert(!valid_copyable_box); // not an object type -static_assert(!valid_copyable_box); // not an object type -static_assert(!valid_copyable_box); - -// primary template -static_assert(sizeof(std::ranges::__copyable_box) == sizeof(std::optional)); - -// optimization #1 -static_assert(sizeof(std::ranges::__copyable_box) == sizeof(Copyable)); -static_assert(alignof(std::ranges::__copyable_box) == alignof(Copyable)); - -// optimization #2 -static_assert(sizeof(std::ranges::__copyable_box) == sizeof(NothrowCopyConstructible)); -static_assert(alignof(std::ranges::__copyable_box) == alignof(NothrowCopyConstructible)); diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/arrow.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/arrow.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/arrow.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/arrow.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/arrow.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/arrow.pass.cpp @@ -19,11 +19,11 @@ #include "types.h" -template +template constexpr void check() { // non-const version { - std::ranges::__copyable_box x(std::in_place, 10); + std::ranges::__movable_box x(std::in_place, 10); T* result = x.operator->(); static_assert(noexcept(x.operator->())); assert(result->value == 10); @@ -32,7 +32,7 @@ // const version { - std::ranges::__copyable_box const x(std::in_place, 10); + std::ranges::__movable_box const x(std::in_place, 10); const T* result = x.operator->(); static_assert(noexcept(x.operator->())); assert(result->value == 10); @@ -41,8 +41,8 @@ } constexpr bool test() { - check(); // primary template - check(); // optimization #1 + check(); // primary template + check(); // optimization #1 check(); // optimization #2 return true; } diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.copy.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/assign.copy.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.copy.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/assign.copy.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.copy.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/assign.copy.pass.cpp @@ -24,8 +24,8 @@ constexpr bool test() { // Test the primary template { - using Box = std::ranges::__copyable_box; - static_assert( std::is_copy_assignable_v); + using Box = std::ranges::__movable_box; + static_assert(std::is_copy_assignable_v); static_assert(!std::is_nothrow_copy_assignable_v); { @@ -51,8 +51,8 @@ // Test optimization #1 for copy-assignment { - using Box = std::ranges::__copyable_box; - static_assert( std::is_copy_assignable_v); + using Box = std::ranges::__movable_box; + static_assert(std::is_copy_assignable_v); static_assert(!std::is_nothrow_copy_assignable_v); { @@ -80,7 +80,7 @@ // Test optimization #2 for copy-assignment { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; static_assert(std::is_copy_assignable_v); static_assert(std::is_nothrow_copy_assignable_v); @@ -112,7 +112,7 @@ // through throwing an exception. #if !defined(TEST_HAS_NO_EXCEPTIONS) void test_empty_state() { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; // assign non-empty to empty { @@ -137,7 +137,7 @@ } // assign empty to empty { - Box x = create_empty_box(); + Box x = create_empty_box(); Box const y = create_empty_box(); Box& result = (x = y); @@ -147,7 +147,7 @@ } // check self-assignment in empty case { - Box x = create_empty_box(); + Box x = create_empty_box(); Box& result = (x = x); assert(&result == &x); diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.move.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/assign.move.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.move.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/assign.move.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.move.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/assign.move.pass.cpp @@ -24,8 +24,8 @@ constexpr bool test() { // Test the primary template { - using Box = std::ranges::__copyable_box; - static_assert( std::is_move_assignable_v); + using Box = std::ranges::__movable_box; + static_assert(std::is_move_assignable_v); static_assert(!std::is_nothrow_move_assignable_v); { @@ -51,9 +51,10 @@ // Make sure that we use the native move assignment in the primary template if we can. { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; static_assert(std::is_move_assignable_v); - static_assert(std::is_nothrow_move_assignable_v == std::is_nothrow_move_assignable_v); + static_assert( + std::is_nothrow_move_assignable_v == std::is_nothrow_move_assignable_v); { Box x(std::in_place, 5); @@ -80,8 +81,8 @@ // Test optimization #1 for move assignment { - using Box = std::ranges::__copyable_box; - static_assert( std::is_move_assignable_v); + using Box = std::ranges::__movable_box; + static_assert(std::is_move_assignable_v); static_assert(!std::is_nothrow_move_assignable_v); { @@ -109,9 +110,10 @@ // Test optimization #1 for move assignment with a type that uses optimization #2 for copy assignment { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; static_assert(std::is_move_assignable_v); - static_assert(std::is_nothrow_move_assignable_v == std::is_nothrow_move_assignable_v); + static_assert( + std::is_nothrow_move_assignable_v == std::is_nothrow_move_assignable_v); { Box x(std::in_place, 5); @@ -138,7 +140,7 @@ // Test optimization #2 for move assignment { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; static_assert(std::is_move_assignable_v); static_assert(std::is_nothrow_move_assignable_v); @@ -170,7 +172,7 @@ // through throwing an exception. #if !defined(TEST_HAS_NO_EXCEPTIONS) void test_empty_state() { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; // assign non-empty to empty { @@ -186,7 +188,7 @@ // assign empty to non-empty { Box x(std::in_place, 5); - Box y = create_empty_box(); + Box y = create_empty_box(); Box& result = (x = std::move(y)); assert(&result == &x); @@ -195,8 +197,8 @@ } // assign empty to empty { - Box x = create_empty_box(); - Box y = create_empty_box(); + Box x = create_empty_box(); + Box y = create_empty_box(); Box& result = (x = std::move(y)); assert(&result == &x); @@ -205,7 +207,7 @@ } // check self-assignment in empty case { - Box x = create_empty_box(); + Box x = create_empty_box(); Box& result = (x = std::move(x)); assert(&result == &x); diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.default.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/ctor.default.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.default.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/ctor.default.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.default.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/ctor.default.pass.cpp @@ -18,19 +18,19 @@ #include "types.h" -template -using Box = std::ranges::__copyable_box; +template +using Box = std::ranges::__movable_box; struct NoDefault { NoDefault() = delete; }; static_assert(!std::is_default_constructible_v>); -template +template struct DefaultNoexcept { DefaultNoexcept() noexcept(Noexcept); }; -static_assert( std::is_nothrow_default_constructible_v>>); +static_assert(std::is_nothrow_default_constructible_v>>); static_assert(!std::is_nothrow_default_constructible_v>>); constexpr bool test() { diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.in_place.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/ctor.in_place.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.in_place.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/ctor.in_place.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.in_place.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/ctor.in_place.pass.cpp @@ -19,9 +19,9 @@ #include "types.h" -struct UnknownType { }; +struct UnknownType {}; -template +template struct NothrowConstructible { explicit NothrowConstructible(int) noexcept(Noexcept); }; @@ -29,7 +29,7 @@ constexpr bool test() { // Test the primary template { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; Box x(std::in_place, 5); assert((*x).value == 5); @@ -38,7 +38,7 @@ // Test optimization #1 { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; Box x(std::in_place, 5); assert((*x).value == 5); @@ -47,15 +47,17 @@ // Test optimization #2 { - using Box = std::ranges::__copyable_box; + using Box = std::ranges::__movable_box; Box x(std::in_place, 5); assert((*x).value == 5); static_assert(!std::is_constructible_v); } - static_assert( std::is_nothrow_constructible_v>, std::in_place_t, int>); - static_assert(!std::is_nothrow_constructible_v>, std::in_place_t, int>); + static_assert( + std::is_nothrow_constructible_v>, std::in_place_t, int>); + static_assert( + !std::is_nothrow_constructible_v>, std::in_place_t, int>); return true; } diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/deref.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/deref.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/deref.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/deref.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/deref.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/deref.pass.cpp @@ -19,11 +19,11 @@ #include "types.h" -template +template constexpr void check() { // non-const version { - std::ranges::__copyable_box x(std::in_place, 10); + std::ranges::__movable_box x(std::in_place, 10); T& result = *x; static_assert(noexcept(*x)); assert(result.value == 10); @@ -31,7 +31,7 @@ // const version { - std::ranges::__copyable_box const x(std::in_place, 10); + std::ranges::__movable_box const x(std::in_place, 10); T const& result = *x; static_assert(noexcept(*x)); assert(result.value == 10); @@ -39,8 +39,8 @@ } constexpr bool test() { - check(); // primary template - check(); // optimization #1 + check(); // primary template + check(); // optimization #1 check(); // optimization #2 return true; } diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/has_value.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/has_value.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/has_value.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/has_value.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/has_value.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/has_value.pass.cpp @@ -18,15 +18,15 @@ #include "types.h" -template +template constexpr void check() { - std::ranges::__copyable_box const x(std::in_place, 10); + std::ranges::__movable_box const x(std::in_place, 10); assert(x.__has_value()); } constexpr bool test() { - check(); // primary template - check(); // optimization #1 + check(); // primary template + check(); // optimization #1 check(); // optimization #2 return true; } @@ -39,7 +39,7 @@ // through throwing an exception. #if !defined(TEST_HAS_NO_EXCEPTIONS) { - std::ranges::__copyable_box x = create_empty_box(); + std::ranges::__movable_box x = create_empty_box(); assert(!x.__has_value()); } #endif diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/no_unique_address.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/no_unique_address.pass.cpp rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/no_unique_address.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/no_unique_address.pass.cpp --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/no_unique_address.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/no_unique_address.pass.cpp @@ -16,19 +16,19 @@ #include bool copied = false; -bool moved = false; +bool moved = false; struct Empty { - Empty() noexcept { } + Empty() noexcept {} Empty(Empty const&) noexcept { copied = true; } Empty(Empty&&) noexcept { moved = true; } Empty& operator=(Empty const&) = delete; - Empty& operator=(Empty&&) = delete; + Empty& operator=(Empty&&) = delete; }; -using Box = std::ranges::__copyable_box; +using Box = std::ranges::__movable_box; -struct Inherit : Box { }; +struct Inherit : Box {}; struct Hold : Box { [[no_unique_address]] Inherit member; @@ -37,7 +37,7 @@ int main(int, char**) { Hold box; - Box& base = static_cast(box); + Box& base = static_cast(box); Box& member = static_cast(box.member); // Despite [[no_unique_address]], the two objects have the same type so they diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/properties.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/properties.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/properties.compile.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// Test various properties of + +#include + +#include + +#include "MoveOnly.h" + +#include "types.h" + +template +constexpr bool valid_movable_box = requires { typename std::ranges::__movable_box; }; + +struct NotCopyConstructible { + NotCopyConstructible() = default; + NotCopyConstructible(NotCopyConstructible&&) = default; + NotCopyConstructible(NotCopyConstructible const&) = delete; + NotCopyConstructible& operator=(NotCopyConstructible&&) = default; + NotCopyConstructible& operator=(NotCopyConstructible const&) = default; +}; + +static_assert(!valid_movable_box); // not an object type +static_assert(!valid_movable_box); // not an object type + +#if _LIBCPP_STD_VER >= 23 +struct NotCopyConstructibleNotMoveConstructible { + NotCopyConstructibleNotMoveConstructible() = default; + NotCopyConstructibleNotMoveConstructible(NotCopyConstructibleNotMoveConstructible&&) = delete; + NotCopyConstructibleNotMoveConstructible(NotCopyConstructibleNotMoveConstructible const&) = delete; + NotCopyConstructibleNotMoveConstructible& operator=(NotCopyConstructibleNotMoveConstructible&&) = delete; + NotCopyConstructibleNotMoveConstructible& operator=(NotCopyConstructibleNotMoveConstructible const&) = delete; +}; + +// [P2494R2] Relaxing range adaptors to allow for move only types. +static_assert(!valid_movable_box); +static_assert(valid_movable_box); +static_assert(valid_movable_box); +#else +static_assert(!valid_movable_box); +#endif + +// primary template +static_assert(sizeof(std::ranges::__movable_box) == sizeof(std::optional)); + +// optimization #1 +static_assert(sizeof(std::ranges::__movable_box) == sizeof(Copyable)); +static_assert(alignof(std::ranges::__movable_box) == alignof(Copyable)); + +// optimization #2 +static_assert(sizeof(std::ranges::__movable_box) == sizeof(NothrowCopyConstructible)); +static_assert(alignof(std::ranges::__movable_box) == alignof(NothrowCopyConstructible)); diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/types.h b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/types.h rename from libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/types.h rename to libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/types.h --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/types.h +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.move.wrap/types.h @@ -16,15 +16,15 @@ #include "test_macros.h" -// NOTE: These types are strongly tied to the implementation of __copyable_box. See the documentation -// in __copyable_box for the meaning of optimizations #1 and #2. +// NOTE: These types are strongly tied to the implementation of __movable_box. See the documentation +// in __movable_box for the meaning of optimizations #1 and #2. // Copy constructible, but neither copyable nor nothrow_copy/move_constructible. This uses the primary template. struct CopyConstructible { constexpr CopyConstructible() = default; - constexpr explicit CopyConstructible(int x) : value(x) { } + constexpr explicit CopyConstructible(int x) : value(x) {} CopyConstructible(CopyConstructible const&) noexcept(false) = default; - CopyConstructible& operator=(CopyConstructible const&) = delete; + CopyConstructible& operator=(CopyConstructible const&) = delete; int value = -1; }; @@ -33,105 +33,102 @@ static_assert(!std::movable); static_assert(!std::is_nothrow_move_constructible_v); - // Copy constructible and movable, but not copyable. This uses the primary template, however we're // still able to use the native move-assignment operator in this case. struct CopyConstructibleMovable { constexpr CopyConstructibleMovable() = default; - constexpr explicit CopyConstructibleMovable(int x) : value(x) { } + constexpr explicit CopyConstructibleMovable(int x) : value(x) {} CopyConstructibleMovable(CopyConstructibleMovable const&) noexcept(false) = default; - CopyConstructibleMovable(CopyConstructibleMovable&&) noexcept(false) = default; - CopyConstructibleMovable& operator=(CopyConstructibleMovable const&) = delete; + CopyConstructibleMovable(CopyConstructibleMovable&&) noexcept(false) = default; + CopyConstructibleMovable& operator=(CopyConstructibleMovable const&) = delete; constexpr CopyConstructibleMovable& operator=(CopyConstructibleMovable&& other) { - value = other.value; + value = other.value; did_move_assign = true; return *this; } - int value = -1; + int value = -1; bool did_move_assign = false; }; - // Copyable type that is not nothrow_copy/move_constructible. // This triggers optimization #1 for the copy assignment and the move assignment. struct Copyable { constexpr Copyable() = default; - constexpr explicit Copyable(int x) : value(x) { } + constexpr explicit Copyable(int x) : value(x) {} Copyable(Copyable const&) noexcept(false) = default; constexpr Copyable& operator=(Copyable const& other) noexcept(false) { - value = other.value; + value = other.value; did_copy_assign = true; return *this; } constexpr Copyable& operator=(Copyable&& other) noexcept(false) { - value = other.value; + value = other.value; did_move_assign = true; return *this; } - int value = -1; + int value = -1; bool did_copy_assign = false; bool did_move_assign = false; }; -static_assert( std::copyable); +static_assert(std::copyable); static_assert(!std::is_nothrow_copy_constructible_v); -static_assert( std::movable); +static_assert(std::movable); static_assert(!std::is_nothrow_move_constructible_v); - // Non-copyable type that is nothrow_copy_constructible and nothrow_move_constructible. // This triggers optimization #2 for the copy assignment and the move assignment. struct NothrowCopyConstructible { constexpr NothrowCopyConstructible() = default; - constexpr explicit NothrowCopyConstructible(int x) : value(x) { } - NothrowCopyConstructible(NothrowCopyConstructible const&) noexcept = default; - NothrowCopyConstructible(NothrowCopyConstructible&&) noexcept = default; + constexpr explicit NothrowCopyConstructible(int x) : value(x) {} + NothrowCopyConstructible(NothrowCopyConstructible const&) noexcept = default; + NothrowCopyConstructible(NothrowCopyConstructible&&) noexcept = default; NothrowCopyConstructible& operator=(NothrowCopyConstructible const&) = delete; int value = -1; }; static_assert(!std::copyable); -static_assert( std::is_nothrow_copy_constructible_v); +static_assert(std::is_nothrow_copy_constructible_v); static_assert(!std::movable); -static_assert( std::is_nothrow_move_constructible_v); - +static_assert(std::is_nothrow_move_constructible_v); // Non-copyable type that is nothrow_copy_constructible, and that is movable but NOT nothrow_move_constructible. // This triggers optimization #2 for the copy assignment, and optimization #1 for the move assignment. struct MovableNothrowCopyConstructible { constexpr MovableNothrowCopyConstructible() = default; - constexpr explicit MovableNothrowCopyConstructible(int x) : value(x) { } - MovableNothrowCopyConstructible(MovableNothrowCopyConstructible const&) noexcept = default; + constexpr explicit MovableNothrowCopyConstructible(int x) : value(x) {} + MovableNothrowCopyConstructible(MovableNothrowCopyConstructible const&) noexcept = default; MovableNothrowCopyConstructible(MovableNothrowCopyConstructible&&) noexcept(false) = default; constexpr MovableNothrowCopyConstructible& operator=(MovableNothrowCopyConstructible&& other) { - value = other.value; + value = other.value; did_move_assign = true; return *this; } - int value = -1; + int value = -1; bool did_move_assign = false; }; static_assert(!std::copyable); -static_assert( std::is_nothrow_copy_constructible_v); -static_assert( std::movable); +static_assert(std::is_nothrow_copy_constructible_v); +static_assert(std::movable); static_assert(!std::is_nothrow_move_constructible_v); - #if !defined(TEST_HAS_NO_EXCEPTIONS) // A type that we can make throw when copied from. This is used to create a // copyable-box in the empty state. static constexpr int THROW_WHEN_COPIED_FROM = 999; struct ThrowsOnCopy { constexpr ThrowsOnCopy() = default; - constexpr explicit ThrowsOnCopy(int x) : value(x) { } + constexpr explicit ThrowsOnCopy(int x) : value(x) {} ThrowsOnCopy(ThrowsOnCopy const& other) { - if (other.value == THROW_WHEN_COPIED_FROM) throw 0; - else value = other.value; + if (other.value == THROW_WHEN_COPIED_FROM) + throw 0; + else + value = other.value; } ThrowsOnCopy& operator=(ThrowsOnCopy const&) = delete; // prevent from being copyable @@ -142,9 +139,9 @@ // Creates an empty box. The only way to do that is to try assigning one box // to another and have that fail due to an exception when calling the copy // constructor. The assigned-to box will then be in the empty state. -inline std::ranges::__copyable_box create_empty_box() { - std::ranges::__copyable_box box1; - std::ranges::__copyable_box box2(std::in_place, THROW_WHEN_COPIED_FROM); +inline std::ranges::__movable_box create_empty_box() { + std::ranges::__movable_box box1; + std::ranges::__movable_box box2(std::in_place, THROW_WHEN_COPIED_FROM); try { box1 = box2; // throws during assignment, which is implemented as a call to the copy ctor } catch (...) { diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp @@ -19,7 +19,7 @@ __cpp_lib_clamp 201603L [C++17] __cpp_lib_constexpr_algorithms 201806L [C++20] __cpp_lib_parallel_algorithm 201603L [C++17] - __cpp_lib_ranges 202106L [C++20] + __cpp_lib_ranges 202207L [C++20] __cpp_lib_ranges_starts_ends_with 202106L [C++23] __cpp_lib_robust_nonmodifying_seq_ops 201304L [C++14] __cpp_lib_sample 201603L [C++17] @@ -184,8 +184,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++20" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++20" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++20" # endif # ifdef __cpp_lib_ranges_starts_ends_with @@ -245,8 +245,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++23" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++23" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++23" # endif # if !defined(_LIBCPP_VERSION) @@ -315,8 +315,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++26" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++26" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++26" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp @@ -28,7 +28,7 @@ __cpp_lib_invoke_r 202106L [C++23] __cpp_lib_move_only_function 202110L [C++23] __cpp_lib_not_fn 201603L [C++17] - __cpp_lib_ranges 202106L [C++20] + __cpp_lib_ranges 202207L [C++20] __cpp_lib_result_of_sfinae 201210L [C++14] __cpp_lib_transparent_operators 201210L [C++14] 201510L [C++17] @@ -293,8 +293,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++20" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++20" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++20" # endif # ifndef __cpp_lib_result_of_sfinae @@ -399,8 +399,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++23" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++23" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++23" # endif # ifndef __cpp_lib_result_of_sfinae @@ -523,8 +523,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++26" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++26" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++26" # endif # ifndef __cpp_lib_result_of_sfinae diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp @@ -23,7 +23,7 @@ __cpp_lib_move_iterator_concept 202207L [C++20] __cpp_lib_nonmember_container_access 201411L [C++17] __cpp_lib_null_iterators 201304L [C++14] - __cpp_lib_ranges 202106L [C++20] + __cpp_lib_ranges 202207L [C++20] __cpp_lib_ssize 201902L [C++20] */ @@ -197,8 +197,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++20" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++20" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++20" # endif # ifndef __cpp_lib_ssize @@ -255,8 +255,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++23" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++23" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++23" # endif # ifndef __cpp_lib_ssize @@ -313,8 +313,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++26" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++26" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++26" # endif # ifndef __cpp_lib_ssize diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp @@ -27,7 +27,7 @@ __cpp_lib_enable_shared_from_this 201603L [C++17] __cpp_lib_make_unique 201304L [C++14] __cpp_lib_out_ptr 202106L [C++23] - __cpp_lib_ranges 202106L [C++20] + __cpp_lib_ranges 202207L [C++20] __cpp_lib_raw_memory_algorithms 201606L [C++17] __cpp_lib_shared_ptr_arrays 201611L [C++17] 201707L [C++20] @@ -363,8 +363,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++20" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++20" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++20" # endif # ifndef __cpp_lib_raw_memory_algorithms @@ -500,8 +500,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++23" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++23" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++23" # endif # ifndef __cpp_lib_raw_memory_algorithms @@ -637,8 +637,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++26" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++26" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++26" # endif # ifndef __cpp_lib_raw_memory_algorithms diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp @@ -16,7 +16,7 @@ // Test the feature test macros defined by /* Constant Value - __cpp_lib_ranges 202106L [C++20] + __cpp_lib_ranges 202207L [C++20] __cpp_lib_ranges_as_rvalue 202207L [C++23] __cpp_lib_ranges_chunk 202202L [C++23] __cpp_lib_ranges_chunk_by 202202L [C++23] @@ -123,8 +123,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++20" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++20" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++20" # endif # ifdef __cpp_lib_ranges_as_rvalue @@ -156,8 +156,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++23" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++23" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++23" # endif # ifndef __cpp_lib_ranges_as_rvalue @@ -237,8 +237,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++26" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++26" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++26" # endif # ifndef __cpp_lib_ranges_as_rvalue diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -139,7 +139,7 @@ __cpp_lib_parallel_algorithm 201603L [C++17] __cpp_lib_polymorphic_allocator 201902L [C++20] __cpp_lib_quoted_string_io 201304L [C++14] - __cpp_lib_ranges 202106L [C++20] + __cpp_lib_ranges 202207L [C++20] __cpp_lib_ranges_as_rvalue 202207L [C++23] __cpp_lib_ranges_chunk 202202L [C++23] __cpp_lib_ranges_chunk_by 202202L [C++23] @@ -3540,8 +3540,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++20" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++20" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++20" # endif # ifdef __cpp_lib_ranges_as_rvalue @@ -4899,8 +4899,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++23" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++23" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++23" # endif # ifndef __cpp_lib_ranges_as_rvalue @@ -6438,8 +6438,8 @@ # ifndef __cpp_lib_ranges # error "__cpp_lib_ranges should be defined in c++26" # endif -# if __cpp_lib_ranges != 202106L -# error "__cpp_lib_ranges should have the value 202106L in c++26" +# if __cpp_lib_ranges != 202207L +# error "__cpp_lib_ranges should have the value 202207L in c++26" # endif # ifndef __cpp_lib_ranges_as_rvalue diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/general.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/general.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.transform/general.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/general.pass.cpp @@ -22,6 +22,7 @@ #include #include +#include "MoveOnly.h" #include "test_macros.h" #include "test_iterators.h" #include "types.h" @@ -47,6 +48,15 @@ }); } +#if _LIBCPP_STD_VER >= 23 +struct MoveOnlyFunction : public MoveOnly { + template + constexpr T operator()(T x) const { + return x + 42; + } +}; +#endif + struct NonConstView : std::ranges::view_base { explicit NonConstView(int *b, int *e) : b_(b), e_(e) {} const int *begin() { return b_; } // deliberately non-const @@ -87,6 +97,16 @@ std::string_view check = "HELLO, WORLD."; assert(std::equal(upp.begin(), upp.end(), check.begin(), check.end())); } +#if _LIBCPP_STD_VER >= 23 + // [P2494R2] Relaxing range adaptors to allow for move only types. + // Test transform_view is valid when the function object is a move only type. + { + int a[] = {1, 2, 3, 4}; + auto transformed = NonConstView(a, a + 4) | std::views::transform(MoveOnlyFunction()); + int expected[] = {43, 44, 45, 46}; + assert(std::equal(transformed.begin(), transformed.end(), expected, expected + 4)); + } +#endif return 0; } diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/cpo.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/cpo.pass.cpp --- a/libcxx/test/std/ranges/range.factories/range.single.view/cpo.pass.cpp +++ b/libcxx/test/std/ranges/range.factories/range.single.view/cpo.pass.cpp @@ -19,9 +19,10 @@ // Can't invoke without arguments. static_assert(!std::is_invocable_v); -// Can't invoke with a move-only type. -static_assert(!std::is_invocable_v); - +#if _LIBCPP_STD_VER >= 23 +// Can invoke with a move-only type. +static_assert(std::is_invocable_v); +#endif constexpr bool test() { // Lvalue. { diff --git a/libcxx/utils/data/ignore_format.txt b/libcxx/utils/data/ignore_format.txt --- a/libcxx/utils/data/ignore_format.txt +++ b/libcxx/utils/data/ignore_format.txt @@ -413,7 +413,6 @@ libcxx/include/__ranges/all.h libcxx/include/__ranges/common_view.h libcxx/include/__ranges/concepts.h -libcxx/include/__ranges/copyable_box.h libcxx/include/__ranges/counted.h libcxx/include/__ranges/data.h libcxx/include/__ranges/drop_view.h diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -778,7 +778,7 @@ }, { "name": "__cpp_lib_ranges", - "values": {"c++20": 202106}, + "values": {"c++20": 202207}, "headers": ["algorithm", "functional", "iterator", "memory", "ranges"], }, { diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -680,7 +680,7 @@ "__ranges/common_view.h", "__ranges/concepts.h", "__ranges/container_compatible_range.h", - "__ranges/copyable_box.h", + "__ranges/movable_box.h", "__ranges/counted.h", "__ranges/dangling.h", "__ranges/data.h",