--------------------------------------------------- -----------------
``__cpp_lib_polymorphic_allocator`` ``201902L``
--------------------------------------------------- -----------------
- ``__cpp_lib_ranges`` ``202106L``
+ ``__cpp_lib_ranges`` ``202207L``
--------------------------------------------------- -----------------
``__cpp_lib_remove_cvref`` ``201711L``
--------------------------------------------------- -----------------
"`P2465R3 <https://wg21.link/P2465R3>`__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","",""
"`P2467R1 <https://wg21.link/P2467R1>`__","LWG","Support exclusive mode for ``fstreams``","July 2022","",""
"`P2474R2 <https://wg21.link/P2474R2>`__","LWG","``views::repeat``","July 2022","","","|ranges|"
-"`P2494R2 <https://wg21.link/P2494R2>`__","LWG","Relaxing range adaptors to allow for move only types","July 2022","","","|ranges|"
+"`P2494R2 <https://wg21.link/P2494R2>`__","LWG","Relaxing range adaptors to allow for move only types","July 2022","|Complete|","17.0","|ranges|"
"`P2499R0 <https://wg21.link/P2499R0>`__","LWG","``string_view`` range constructor should be ``explicit``","July 2022","|Complete|","16.0","|ranges|"
"`P2502R2 <https://wg21.link/P2502R2>`__","LWG","``std::generator``: Synchronous Coroutine Generator for Ranges","July 2022","","","|ranges|"
"`P2508R1 <https://wg21.link/P2508R1>`__","LWG","Exposing ``std::basic-format-string``","July 2022","|Complete|","15.0"
__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
__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
+++ /dev/null
-// -*- 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 <optional>
-
-#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<class _Tp>
-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<class ..._Args>
- 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<class _Tp>
- concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>;
-
- template<class _Tp>
- 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<class ..._Args>
- 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
#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>
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<iterator_t<_View>>, __empty_cache>;
#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>
requires view<_View> && is_object_v<_Pred>
class filter_view : public view_interface<filter_view<_View, _Pred>> {
_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.
#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>
--- /dev/null
+// -*- 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 <optional>
+
+#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 <class _Tp>
+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 <class... _Args>
+ 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 <class _Tp>
+concept __doesnt_need_empty_state =
+ (copy_constructible<_Tp>
+ // 1. If copy_constructible<T> is true, movable-box<T> should store only a T if either T models
+ // copyable, or is_nothrow_move_constructible_v<T> && is_nothrow_copy_constructible_v<T> is true.
+ ? copyable<_Tp> || (is_nothrow_move_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Tp>)
+ // 2. Otherwise, movable-box<T> should store only a T if either T models movable or
+ // is_nothrow_move_constructible_v<T> is true.
+ : movable<_Tp> || is_nothrow_move_constructible_v<_Tp>);
+# else
+
+template <class _Tp>
+concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>;
+
+template <class _Tp>
+concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>;
+
+template <class _Tp>
+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 <class... _Args>
+ 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
#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>
#if _LIBCPP_STD_VER >= 20
namespace ranges {
- template<copy_constructible _Tp>
- requires is_object_v<_Tp>
- class single_view : public view_interface<single_view<_Tp>> {
- __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<class... _Args>
- requires constructible_from<_Tp, _Args...>
- _LIBCPP_HIDE_FROM_ABI
- constexpr explicit single_view(in_place_t, _Args&&... __args)
+# if _LIBCPP_STD_VER >= 23
+template <move_constructible _Tp>
+# else
+template <copy_constructible _Tp>
+# endif
+ requires is_object_v<_Tp>
+class single_view : public view_interface<single_view<_Tp>> {
+ __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 <class... _Args>
+ 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<class _Tp>
single_view(_Tp) -> single_view<_Tp>;
#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>
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()
#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>
regular_invocable<_Fn&, range_reference_t<_View>> &&
__can_reference<invoke_result_t<_Fn&, range_reference_t<_View>>>;
-template<input_range _View, copy_constructible _Fn>
+# if _LIBCPP_STD_VER >= 23
+template <input_range _View, move_constructible _Fn>
+# else
+template <input_range _View, copy_constructible _Fn>
+# endif
requires __transform_view_constraints<_View, _Fn>
class transform_view : public view_interface<transform_view<_View, _Fn>> {
template<bool> class __iterator;
template<bool> 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:
>;
};
-template<input_range _View, copy_constructible _Fn>
+# if _LIBCPP_STD_VER >= 23
+template <input_range _View, move_constructible _Fn>
+# else
+template <input_range _View, copy_constructible _Fn>
+# endif
requires __transform_view_constraints<_View, _Fn>
-template<bool _Const>
-class transform_view<_View, _Fn>::__iterator
- : public __transform_view_iterator_category_base<_View, _Fn> {
+template <bool _Const>
+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>;
}
};
-template<input_range _View, copy_constructible _Fn>
+# if _LIBCPP_STD_VER >= 23
+template <input_range _View, move_constructible _Fn>
+# else
+template <input_range _View, copy_constructible _Fn>
+# endif
requires __transform_view_constraints<_View, _Fn>
-template<bool _Const>
+template <bool _Const>
class transform_view<_View, _Fn>::__sentinel {
using _Parent = __maybe_const<_Const, transform_view>;
using _Base = __maybe_const<_Const, _View>;
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
}
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" }
__cpp_lib_parallel_algorithm 201603L <algorithm> <numeric>
__cpp_lib_polymorphic_allocator 201902L <memory_resource>
__cpp_lib_quoted_string_io 201304L <iomanip>
-__cpp_lib_ranges 202106L <algorithm> <functional> <iterator>
+__cpp_lib_ranges 202207L <algorithm> <functional> <iterator>
<memory> <ranges>
__cpp_lib_ranges_as_rvalue 202207L <ranges>
__cpp_lib_ranges_chunk 202202L <ranges>
# 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
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// 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 <copyable-box>
-
-#include <ranges>
-
-#include <optional>
-
-#include "types.h"
-
-template <class T>
-constexpr bool valid_copyable_box = requires {
- typename std::ranges::__copyable_box<T>;
-};
-
-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<void>); // not an object type
-static_assert(!valid_copyable_box<int&>); // not an object type
-static_assert(!valid_copyable_box<NotCopyConstructible>);
-
-// primary template
-static_assert(sizeof(std::ranges::__copyable_box<CopyConstructible>) == sizeof(std::optional<CopyConstructible>));
-
-// optimization #1
-static_assert(sizeof(std::ranges::__copyable_box<Copyable>) == sizeof(Copyable));
-static_assert(alignof(std::ranges::__copyable_box<Copyable>) == alignof(Copyable));
-
-// optimization #2
-static_assert(sizeof(std::ranges::__copyable_box<NothrowCopyConstructible>) == sizeof(NothrowCopyConstructible));
-static_assert(alignof(std::ranges::__copyable_box<NothrowCopyConstructible>) == alignof(NothrowCopyConstructible));
#include "types.h"
-template<class T>
+template <class T>
constexpr void check() {
// non-const version
{
- std::ranges::__copyable_box<T> x(std::in_place, 10);
+ std::ranges::__movable_box<T> x(std::in_place, 10);
T* result = x.operator->();
static_assert(noexcept(x.operator->()));
assert(result->value == 10);
// const version
{
- std::ranges::__copyable_box<T> const x(std::in_place, 10);
+ std::ranges::__movable_box<T> const x(std::in_place, 10);
const T* result = x.operator->();
static_assert(noexcept(x.operator->()));
assert(result->value == 10);
}
constexpr bool test() {
- check<CopyConstructible>(); // primary template
- check<Copyable>(); // optimization #1
+ check<CopyConstructible>(); // primary template
+ check<Copyable>(); // optimization #1
check<NothrowCopyConstructible>(); // optimization #2
return true;
}
constexpr bool test() {
// Test the primary template
{
- using Box = std::ranges::__copyable_box<CopyConstructible>;
- static_assert( std::is_copy_assignable_v<Box>);
+ using Box = std::ranges::__movable_box<CopyConstructible>;
+ static_assert(std::is_copy_assignable_v<Box>);
static_assert(!std::is_nothrow_copy_assignable_v<Box>);
{
// Test optimization #1 for copy-assignment
{
- using Box = std::ranges::__copyable_box<Copyable>;
- static_assert( std::is_copy_assignable_v<Box>);
+ using Box = std::ranges::__movable_box<Copyable>;
+ static_assert(std::is_copy_assignable_v<Box>);
static_assert(!std::is_nothrow_copy_assignable_v<Box>);
{
// Test optimization #2 for copy-assignment
{
- using Box = std::ranges::__copyable_box<NothrowCopyConstructible>;
+ using Box = std::ranges::__movable_box<NothrowCopyConstructible>;
static_assert(std::is_copy_assignable_v<Box>);
static_assert(std::is_nothrow_copy_assignable_v<Box>);
// through throwing an exception.
#if !defined(TEST_HAS_NO_EXCEPTIONS)
void test_empty_state() {
- using Box = std::ranges::__copyable_box<ThrowsOnCopy>;
+ using Box = std::ranges::__movable_box<ThrowsOnCopy>;
// assign non-empty to empty
{
}
// assign empty to empty
{
- Box x = create_empty_box();
+ Box x = create_empty_box();
Box const y = create_empty_box();
Box& result = (x = y);
}
// check self-assignment in empty case
{
- Box x = create_empty_box();
+ Box x = create_empty_box();
Box& result = (x = x);
assert(&result == &x);
constexpr bool test() {
// Test the primary template
{
- using Box = std::ranges::__copyable_box<CopyConstructible>;
- static_assert( std::is_move_assignable_v<Box>);
+ using Box = std::ranges::__movable_box<CopyConstructible>;
+ static_assert(std::is_move_assignable_v<Box>);
static_assert(!std::is_nothrow_move_assignable_v<Box>);
{
// Make sure that we use the native move assignment in the primary template if we can.
{
- using Box = std::ranges::__copyable_box<CopyConstructibleMovable>;
+ using Box = std::ranges::__movable_box<CopyConstructibleMovable>;
static_assert(std::is_move_assignable_v<Box>);
- static_assert(std::is_nothrow_move_assignable_v<Box> == std::is_nothrow_move_assignable_v<CopyConstructibleMovable>);
+ static_assert(
+ std::is_nothrow_move_assignable_v<Box> == std::is_nothrow_move_assignable_v<CopyConstructibleMovable>);
{
Box x(std::in_place, 5);
// Test optimization #1 for move assignment
{
- using Box = std::ranges::__copyable_box<Copyable>;
- static_assert( std::is_move_assignable_v<Box>);
+ using Box = std::ranges::__movable_box<Copyable>;
+ static_assert(std::is_move_assignable_v<Box>);
static_assert(!std::is_nothrow_move_assignable_v<Box>);
{
// Test optimization #1 for move assignment with a type that uses optimization #2 for copy assignment
{
- using Box = std::ranges::__copyable_box<MovableNothrowCopyConstructible>;
+ using Box = std::ranges::__movable_box<MovableNothrowCopyConstructible>;
static_assert(std::is_move_assignable_v<Box>);
- static_assert(std::is_nothrow_move_assignable_v<Box> == std::is_nothrow_move_assignable_v<MovableNothrowCopyConstructible>);
+ static_assert(
+ std::is_nothrow_move_assignable_v<Box> == std::is_nothrow_move_assignable_v<MovableNothrowCopyConstructible>);
{
Box x(std::in_place, 5);
// Test optimization #2 for move assignment
{
- using Box = std::ranges::__copyable_box<NothrowCopyConstructible>;
+ using Box = std::ranges::__movable_box<NothrowCopyConstructible>;
static_assert(std::is_move_assignable_v<Box>);
static_assert(std::is_nothrow_move_assignable_v<Box>);
// through throwing an exception.
#if !defined(TEST_HAS_NO_EXCEPTIONS)
void test_empty_state() {
- using Box = std::ranges::__copyable_box<ThrowsOnCopy>;
+ using Box = std::ranges::__movable_box<ThrowsOnCopy>;
// assign non-empty to empty
{
// 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);
}
// 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);
}
// 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);
#include "types.h"
-template<class T>
-using Box = std::ranges::__copyable_box<T>;
+template <class T>
+using Box = std::ranges::__movable_box<T>;
struct NoDefault {
NoDefault() = delete;
};
static_assert(!std::is_default_constructible_v<Box<NoDefault>>);
-template<bool Noexcept>
+template <bool Noexcept>
struct DefaultNoexcept {
DefaultNoexcept() noexcept(Noexcept);
};
-static_assert( std::is_nothrow_default_constructible_v<Box<DefaultNoexcept<true>>>);
+static_assert(std::is_nothrow_default_constructible_v<Box<DefaultNoexcept<true>>>);
static_assert(!std::is_nothrow_default_constructible_v<Box<DefaultNoexcept<false>>>);
constexpr bool test() {
#include "types.h"
-struct UnknownType { };
+struct UnknownType {};
-template<bool Noexcept>
+template <bool Noexcept>
struct NothrowConstructible {
explicit NothrowConstructible(int) noexcept(Noexcept);
};
constexpr bool test() {
// Test the primary template
{
- using Box = std::ranges::__copyable_box<CopyConstructible>;
+ using Box = std::ranges::__movable_box<CopyConstructible>;
Box x(std::in_place, 5);
assert((*x).value == 5);
// Test optimization #1
{
- using Box = std::ranges::__copyable_box<Copyable>;
+ using Box = std::ranges::__movable_box<Copyable>;
Box x(std::in_place, 5);
assert((*x).value == 5);
// Test optimization #2
{
- using Box = std::ranges::__copyable_box<NothrowCopyConstructible>;
+ using Box = std::ranges::__movable_box<NothrowCopyConstructible>;
Box x(std::in_place, 5);
assert((*x).value == 5);
static_assert(!std::is_constructible_v<Box, std::in_place_t, UnknownType>);
}
- static_assert( std::is_nothrow_constructible_v<std::ranges::__copyable_box<NothrowConstructible<true>>, std::in_place_t, int>);
- static_assert(!std::is_nothrow_constructible_v<std::ranges::__copyable_box<NothrowConstructible<false>>, std::in_place_t, int>);
+ static_assert(
+ std::is_nothrow_constructible_v<std::ranges::__movable_box<NothrowConstructible<true>>, std::in_place_t, int>);
+ static_assert(
+ !std::is_nothrow_constructible_v<std::ranges::__movable_box<NothrowConstructible<false>>, std::in_place_t, int>);
return true;
}
#include "types.h"
-template<class T>
+template <class T>
constexpr void check() {
// non-const version
{
- std::ranges::__copyable_box<T> x(std::in_place, 10);
+ std::ranges::__movable_box<T> x(std::in_place, 10);
T& result = *x;
static_assert(noexcept(*x));
assert(result.value == 10);
// const version
{
- std::ranges::__copyable_box<T> const x(std::in_place, 10);
+ std::ranges::__movable_box<T> const x(std::in_place, 10);
T const& result = *x;
static_assert(noexcept(*x));
assert(result.value == 10);
}
constexpr bool test() {
- check<CopyConstructible>(); // primary template
- check<Copyable>(); // optimization #1
+ check<CopyConstructible>(); // primary template
+ check<Copyable>(); // optimization #1
check<NothrowCopyConstructible>(); // optimization #2
return true;
}
#include "types.h"
-template<class T>
+template <class T>
constexpr void check() {
- std::ranges::__copyable_box<T> const x(std::in_place, 10);
+ std::ranges::__movable_box<T> const x(std::in_place, 10);
assert(x.__has_value());
}
constexpr bool test() {
- check<CopyConstructible>(); // primary template
- check<Copyable>(); // optimization #1
+ check<CopyConstructible>(); // primary template
+ check<Copyable>(); // optimization #1
check<NothrowCopyConstructible>(); // optimization #2
return true;
}
// through throwing an exception.
#if !defined(TEST_HAS_NO_EXCEPTIONS)
{
- std::ranges::__copyable_box<ThrowsOnCopy> x = create_empty_box();
+ std::ranges::__movable_box<ThrowsOnCopy> x = create_empty_box();
assert(!x.__has_value());
}
#endif
#include <utility>
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<Empty>;
+using Box = std::ranges::__movable_box<Empty>;
-struct Inherit : Box { };
+struct Inherit : Box {};
struct Hold : Box {
[[no_unique_address]] Inherit member;
int main(int, char**) {
Hold box;
- Box& base = static_cast<Box&>(box);
+ Box& base = static_cast<Box&>(box);
Box& member = static_cast<Box&>(box.member);
// Despite [[no_unique_address]], the two objects have the same type so they
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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 <copyable-box>
+
+#include <ranges>
+
+#include <optional>
+
+#include "MoveOnly.h"
+
+#include "types.h"
+
+template <class T>
+constexpr bool valid_movable_box = requires { typename std::ranges::__movable_box<T>; };
+
+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<void>); // not an object type
+static_assert(!valid_movable_box<int&>); // 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<NotCopyConstructibleNotMoveConstructible>);
+static_assert(valid_movable_box<NotCopyConstructible>);
+static_assert(valid_movable_box<MoveOnly>);
+#else
+static_assert(!valid_movable_box<NotCopyConstructible>);
+#endif
+
+// primary template
+static_assert(sizeof(std::ranges::__movable_box<CopyConstructible>) == sizeof(std::optional<CopyConstructible>));
+
+// optimization #1
+static_assert(sizeof(std::ranges::__movable_box<Copyable>) == sizeof(Copyable));
+static_assert(alignof(std::ranges::__movable_box<Copyable>) == alignof(Copyable));
+
+// optimization #2
+static_assert(sizeof(std::ranges::__movable_box<NothrowCopyConstructible>) == sizeof(NothrowCopyConstructible));
+static_assert(alignof(std::ranges::__movable_box<NothrowCopyConstructible>) == alignof(NothrowCopyConstructible));
#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;
};
static_assert(!std::movable<CopyConstructible>);
static_assert(!std::is_nothrow_move_constructible_v<CopyConstructible>);
-
// 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<Copyable>);
+static_assert(std::copyable<Copyable>);
static_assert(!std::is_nothrow_copy_constructible_v<Copyable>);
-static_assert( std::movable<Copyable>);
+static_assert(std::movable<Copyable>);
static_assert(!std::is_nothrow_move_constructible_v<Copyable>);
-
// 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<NothrowCopyConstructible>);
-static_assert( std::is_nothrow_copy_constructible_v<NothrowCopyConstructible>);
+static_assert(std::is_nothrow_copy_constructible_v<NothrowCopyConstructible>);
static_assert(!std::movable<NothrowCopyConstructible>);
-static_assert( std::is_nothrow_move_constructible_v<NothrowCopyConstructible>);
-
+static_assert(std::is_nothrow_move_constructible_v<NothrowCopyConstructible>);
// 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<MovableNothrowCopyConstructible>);
-static_assert( std::is_nothrow_copy_constructible_v<MovableNothrowCopyConstructible>);
-static_assert( std::movable<MovableNothrowCopyConstructible>);
+static_assert(std::is_nothrow_copy_constructible_v<MovableNothrowCopyConstructible>);
+static_assert(std::movable<MovableNothrowCopyConstructible>);
static_assert(!std::is_nothrow_move_constructible_v<MovableNothrowCopyConstructible>);
-
#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
// 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<ThrowsOnCopy> create_empty_box() {
- std::ranges::__copyable_box<ThrowsOnCopy> box1;
- std::ranges::__copyable_box<ThrowsOnCopy> box2(std::in_place, THROW_WHEN_COPIED_FROM);
+inline std::ranges::__movable_box<ThrowsOnCopy> create_empty_box() {
+ std::ranges::__movable_box<ThrowsOnCopy> box1;
+ std::ranges::__movable_box<ThrowsOnCopy> 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 (...) {
__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]
# 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
# 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)
# 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)
__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]
# 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
# 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
# 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
__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]
*/
# 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
# 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
# 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
__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]
# 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
# 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
# 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
// Test the feature test macros defined by <ranges>
/* 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]
# 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
# 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
# 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
__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]
# 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
# 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
# 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
#include <vector>
#include <cassert>
+#include "MoveOnly.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "types.h"
});
}
+#if _LIBCPP_STD_VER >= 23
+struct MoveOnlyFunction : public MoveOnly {
+ template <class T>
+ 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
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;
}
// Can't invoke without arguments.
static_assert(!std::is_invocable_v<decltype((std::views::single))>);
-// Can't invoke with a move-only type.
-static_assert(!std::is_invocable_v<decltype((std::views::single)), MoveOnly>);
-
+#if _LIBCPP_STD_VER >= 23
+// Can invoke with a move-only type.
+static_assert(std::is_invocable_v<decltype((std::views::single)), MoveOnly>);
+#endif
constexpr bool test() {
// Lvalue.
{
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
},
{
"name": "__cpp_lib_ranges",
- "values": {"c++20": 202106},
+ "values": {"c++20": 202207},
"headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
},
{
"__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",