[libc++][ranges] P3059R2: Making user-defined constructors of view iterators/sentinels private (#193891)
Implements https://wg21.link/P3059R2 (DR) Closes #189599 1. Made constructors of iterator and sentinel types of the following views private: - `iota_view` - `basic_istream_view` - `filter_view` - `transform_view` - `take_view` - `take_while_view` - `join_view` - `lazy_split_view` - `split_view` - `elements_view` 2. Updated all relevant tests to fix the usages of the now private constructor, including: 1. Removed now obsolete tests (files and cases). 2. Updated all relevant tests to get the iterators and the sentinels via `begin()` and `end()`, wherever applicable . 3. Added test cases to confirm that P3059R2 was implemented properly. 4. Minor other (necessary) tweaks. --------- Co-authored-by: Hristo Hristov <zingam@outlook.com> Co-authored-by: A. Jiang <de34@live.cn>
This commit is contained in:
parent
2f08dff513
commit
11b58f0e4c
50 changed files with 503 additions and 698 deletions
|
|
@ -39,6 +39,7 @@ Implemented Papers
|
|||
------------------
|
||||
|
||||
- P0493R5: Atomic minimum/maximum (`Github <https://llvm.org/PR105418>`__)
|
||||
- P3059R2: Making user-defined constructors of view iterators/sentinels private (`Github <https://github.com/llvm/llvm-project/issues/189599>`__)
|
||||
- P0792R14: ``function_ref`` : a type-erased callable reference (`Github <https://llvm.org/PR105376>`__)
|
||||
- P3948R1: ``constant_wrapper`` is the only tool needed for passing constant expressions via function arguments (`Github <https://llvm.org/PR189604>`__)
|
||||
- P3961R1: Less double indirection in ``function_ref`` (RU-220) (`Github <https://llvm.org/PR189606>`__)
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@
|
|||
"`P4140R0 <https://wg21.link/P4140R0>`__","Proposed resolution for US70-126: allow incomplete types in type_order","2026-03 (Croydon)","","","`#189595 <https://github.com/llvm/llvm-project/issues/189595>`__",""
|
||||
"`P3373R4 <https://wg21.link/P3373R4>`__","Of Operation States and Their Lifetimes","2026-03 (Croydon)","","","`#189597 <https://github.com/llvm/llvm-project/issues/189597>`__",""
|
||||
"`P3986R1 <https://wg21.link/P3986R1>`__","A Wording Strategy for Inlinable Receivers","2026-03 (Croydon)","","","`#189598 <https://github.com/llvm/llvm-project/issues/189598>`__",""
|
||||
"`P3059R2 <https://wg21.link/P3059R2>`__","Making user-defined constructors of view iterators/sentinels private","2026-03 (Croydon)","","","`#189599 <https://github.com/llvm/llvm-project/issues/189599>`__",""
|
||||
"`P3059R2 <https://wg21.link/P3059R2>`__","Making user-defined constructors of view iterators/sentinels private","2026-03 (Croydon)","|Complete|","24","`#189599 <https://github.com/llvm/llvm-project/issues/189599>`__",""
|
||||
"`P3725R3 <https://wg21.link/P3725R3>`__","Filter View Extensions for Safer Use, Rev 3","2026-03 (Croydon)","","","`#189601 <https://github.com/llvm/llvm-project/issues/189601>`__",""
|
||||
"`P3828R1 <https://wg21.link/P3828R1>`__","Rename the to_input view to as_input","2026-03 (Croydon)","","","`#189602 <https://github.com/llvm/llvm-project/issues/189602>`__",""
|
||||
"`P3795R2 <https://wg21.link/P3795R2>`__","Miscellaneous Reflection Cleanup","2026-03 (Croydon)","","","`#189603 <https://github.com/llvm/llvm-project/issues/189603>`__",""
|
||||
|
|
|
|||
|
|
|
@ -165,6 +165,8 @@ template <input_range _View, size_t _Np>
|
|||
template <bool _Const>
|
||||
class elements_view<_View, _Np>::__iterator
|
||||
: public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> {
|
||||
friend class elements_view<_View, _Np>;
|
||||
|
||||
template <bool>
|
||||
friend class __iterator;
|
||||
|
||||
|
|
@ -175,6 +177,8 @@ class elements_view<_View, _Np>::__iterator
|
|||
|
||||
iterator_t<_Base> __current_ = iterator_t<_Base>();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_element(const iterator_t<_Base>& __i) {
|
||||
if constexpr (is_reference_v<range_reference_t<_Base>>) {
|
||||
return std::get<_Np>(*__i);
|
||||
|
|
@ -205,8 +209,6 @@ public:
|
|||
requires default_initializable<iterator_t<_Base>>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
|
||||
requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
|
||||
: __current_(std::move(__i.__current_)) {}
|
||||
|
|
@ -339,6 +341,10 @@ private:
|
|||
using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
|
||||
|
||||
friend class elements_view<_View, _Np>;
|
||||
|
||||
template <bool>
|
||||
friend class __sentinel;
|
||||
|
||||
|
|
@ -350,8 +356,6 @@ private:
|
|||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other)
|
||||
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
|
||||
: __end_(std::move(__other.__end_)) {}
|
||||
|
|
|
|||
|
|
@ -127,10 +127,16 @@ struct __filter_iterator_category<_View> {
|
|||
template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
|
||||
requires view<_View> && is_object_v<_Pred>
|
||||
class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> {
|
||||
public:
|
||||
private:
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>();
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(filter_view& __parent, iterator_t<_View> __current)
|
||||
: __current_(std::move(__current)), __parent_(std::addressof(__parent)) {}
|
||||
|
||||
friend class filter_view<_View, _Pred>;
|
||||
|
||||
public:
|
||||
using iterator_concept =
|
||||
_If<bidirectional_range<_View>,
|
||||
bidirectional_iterator_tag,
|
||||
|
|
@ -145,9 +151,6 @@ public:
|
|||
requires default_initializable<iterator_t<_View>>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(filter_view& __parent, iterator_t<_View> __current)
|
||||
: __current_(std::move(__current)), __parent_(std::addressof(__parent)) {}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> const& base() const& noexcept { return __current_; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() && { return std::move(__current_); }
|
||||
|
||||
|
|
@ -211,13 +214,16 @@ public:
|
|||
template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
|
||||
requires view<_View> && is_object_v<_Pred>
|
||||
class filter_view<_View, _Pred>::__sentinel {
|
||||
public:
|
||||
private:
|
||||
sentinel_t<_View> __end_ = sentinel_t<_View>();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(filter_view& __parent) : __end_(ranges::end(__parent.__base_)) {}
|
||||
|
||||
friend class filter_view<_View, _Pred>;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_View> base() const { return __end_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(__iterator const& __x, __sentinel const& __y) {
|
||||
|
|
|
|||
|
|
@ -110,6 +110,12 @@ template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_
|
|||
requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start>
|
||||
class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
|
||||
struct __iterator : public __iota_iterator_category<_Start> {
|
||||
private:
|
||||
_Start __value_ = _Start();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {}
|
||||
|
||||
public:
|
||||
friend class iota_view;
|
||||
|
||||
using iterator_concept =
|
||||
|
|
@ -124,14 +130,10 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
|
|||
using value_type = _Start;
|
||||
using difference_type = _IotaDiffT<_Start>;
|
||||
|
||||
_Start __value_ = _Start();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __iterator()
|
||||
requires default_initializable<_Start>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Start operator*() const
|
||||
noexcept(is_nothrow_copy_constructible_v<_Start>) {
|
||||
return __value_;
|
||||
|
|
@ -282,11 +284,12 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
|
|||
private:
|
||||
_BoundSentinel __bound_sentinel_ = _BoundSentinel();
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_BoundSentinel __bound_sentinel)
|
||||
: __bound_sentinel_(std::move(__bound_sentinel)) {}
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
|
||||
return __x.__value_ == __y.__bound_sentinel_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,9 +66,6 @@ public:
|
|||
using difference_type = ptrdiff_t;
|
||||
using value_type = _Val;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept
|
||||
: __parent_(std::addressof(__parent)) {}
|
||||
|
||||
__iterator(const __iterator&) = delete;
|
||||
_LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default;
|
||||
|
||||
|
|
@ -91,9 +88,14 @@ public:
|
|||
private:
|
||||
basic_istream_view<_Val, _CharT, _Traits>* __parent_;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept
|
||||
: __parent_(std::addressof(__parent)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr basic_istream<_CharT, _Traits>* __get_parent_stream() const {
|
||||
return __parent_->__stream_;
|
||||
}
|
||||
|
||||
friend class basic_istream_view<_Val, _CharT, _Traits>;
|
||||
};
|
||||
|
||||
template <class _Val>
|
||||
|
|
|
|||
|
|
@ -160,11 +160,13 @@ private:
|
|||
using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
|
||||
sentinel_t<_Base> __end_ = sentinel_t<_Base>();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {}
|
||||
|
||||
friend class join_view<_View>;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
|
||||
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
|
||||
: __end_(std::move(__s.__end_)) {}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,8 @@ private:
|
|||
template <bool _Const>
|
||||
struct __outer_iterator : __outer_iterator_category<__maybe_const<_Const, _View>> {
|
||||
private:
|
||||
friend class lazy_split_view<_View, _Pattern>;
|
||||
|
||||
template <bool>
|
||||
friend struct __inner_iterator;
|
||||
friend __outer_iterator<true>;
|
||||
|
|
@ -155,6 +157,14 @@ private:
|
|||
_LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent();
|
||||
bool __trailing_empty_ = false;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __outer_iterator(_Parent& __parent)
|
||||
requires(!forward_range<_Base>)
|
||||
: __parent_(std::addressof(__parent)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current)
|
||||
requires forward_range<_Base>
|
||||
: __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto& __current() noexcept {
|
||||
if constexpr (forward_range<_View>) {
|
||||
return __current_;
|
||||
|
|
@ -196,14 +206,6 @@ private:
|
|||
|
||||
_LIBCPP_HIDE_FROM_ABI __outer_iterator() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __outer_iterator(_Parent& __parent)
|
||||
requires(!forward_range<_Base>)
|
||||
: __parent_(std::addressof(__parent)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current)
|
||||
requires forward_range<_Base>
|
||||
: __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(__outer_iterator<!_Const> __i)
|
||||
requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
|
||||
: __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {}
|
||||
|
|
@ -286,12 +288,16 @@ private:
|
|||
template <bool _Const>
|
||||
struct __inner_iterator : __inner_iterator_category<__maybe_const<_Const, _View>> {
|
||||
private:
|
||||
friend class lazy_split_view<_View, _Pattern>;
|
||||
|
||||
using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
|
||||
// Workaround for a GCC issue.
|
||||
static constexpr bool _OuterConst = _Const;
|
||||
__outer_iterator<_Const> __i_ = __outer_iterator<_OuterConst>();
|
||||
bool __incremented_ = false;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) : __i_(std::move(__i)) {}
|
||||
|
||||
// Note: these private functions are necessary because GCC doesn't allow calls to private members of `__i_` from
|
||||
// free functions that are friends of `inner-iterator`.
|
||||
|
||||
|
|
@ -342,8 +348,6 @@ private:
|
|||
|
||||
_LIBCPP_HIDE_FROM_ABI __inner_iterator() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) : __i_(std::move(__i)) {}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept {
|
||||
return __i_.__current();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,12 @@ private:
|
|||
_LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>();
|
||||
bool __trailing_empty_ = false;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(
|
||||
split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next)
|
||||
: __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {}
|
||||
|
||||
friend class split_view<_View, _Pattern>;
|
||||
|
||||
friend struct __sentinel;
|
||||
|
||||
public:
|
||||
|
|
@ -137,10 +143,6 @@ public:
|
|||
|
||||
_LIBCPP_HIDE_FROM_ABI __iterator() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(
|
||||
split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next)
|
||||
: __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() const { return __cur_; }
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; }
|
||||
|
|
@ -179,16 +181,18 @@ struct split_view<_View, _Pattern>::__sentinel {
|
|||
private:
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent)
|
||||
: __end_(ranges::end(__parent.__base_)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) {
|
||||
return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_;
|
||||
}
|
||||
|
||||
friend class split_view<_View, _Pattern>;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent)
|
||||
: __end_(ranges::end(__parent.__base_)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
|
||||
return __equals(__x, __y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,14 +165,16 @@ class take_view<_View>::__sentinel {
|
|||
using _Iter _LIBCPP_NODEBUG = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
|
||||
|
||||
friend class take_view<_View>;
|
||||
|
||||
template <bool>
|
||||
friend class take_view<_View>::__sentinel;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
|
||||
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
|
||||
: __end_(std::move(__s.__end_)) {}
|
||||
|
|
|
|||
|
|
@ -108,14 +108,16 @@ class take_while_view<_View, _Pred>::__sentinel {
|
|||
sentinel_t<_Base> __end_ = sentinel_t<_Base>();
|
||||
const _Pred* __pred_ = nullptr;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
|
||||
: __end_(std::move(__end)), __pred_(__pred) {}
|
||||
|
||||
friend class take_while_view<_View, _Pred>;
|
||||
|
||||
friend class __sentinel<!_Const>;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
|
||||
: __end_(std::move(__end)), __pred_(__pred) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
|
||||
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
|
||||
: __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {}
|
||||
|
|
|
|||
|
|
@ -192,6 +192,11 @@ class transform_view<_View, _Fn>::__iterator
|
|||
|
||||
_Parent* __parent_ = nullptr;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current)
|
||||
: __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
|
||||
|
||||
friend class transform_view<_View, _Fn>;
|
||||
|
||||
template <bool>
|
||||
friend class transform_view<_View, _Fn>::__iterator;
|
||||
|
||||
|
|
@ -209,9 +214,6 @@ public:
|
|||
requires default_initializable<iterator_t<_Base>>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current)
|
||||
: __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
|
||||
|
||||
// Note: `__i` should always be `__iterator<false>`, but directly using
|
||||
// `__iterator<false>` is ill-formed when `_Const` is false
|
||||
// (see http://wg21.link/class.copy.ctor#5).
|
||||
|
|
@ -354,6 +356,10 @@ class transform_view<_View, _Fn>::__sentinel {
|
|||
|
||||
sentinel_t<_Base> __end_ = sentinel_t<_Base>();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
|
||||
|
||||
friend class transform_view<_View, _Fn>;
|
||||
|
||||
template <bool>
|
||||
friend class transform_view<_View, _Fn>::__iterator;
|
||||
|
||||
|
|
@ -363,8 +369,6 @@ class transform_view<_View, _Fn>::__sentinel {
|
|||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
|
||||
|
||||
// Note: `__i` should always be `__sentinel<false>`, but directly using
|
||||
// `__sentinel<false>` is ill-formed when `_Const` is false
|
||||
// (see http://wg21.link/class.copy.ctor#5).
|
||||
|
|
|
|||
|
|
@ -37,17 +37,19 @@ LIBCPP_STATIC_ASSERT(!IsBaseNoexcept<ElementsIter&&>);
|
|||
constexpr bool test() {
|
||||
std::tuple<int> t{5};
|
||||
|
||||
std::ranges::elements_view<BaseView, 0> ev{BaseView{&t, &t + 1}};
|
||||
|
||||
// const &
|
||||
{
|
||||
const ElementsIter it{&t};
|
||||
decltype(auto) base = it.base();
|
||||
const ElementsIter it = ev.begin();
|
||||
decltype(auto) base = it.base();
|
||||
static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
|
||||
assert(base == &t);
|
||||
}
|
||||
|
||||
// &
|
||||
{
|
||||
ElementsIter it{&t};
|
||||
ElementsIter it = ev.begin();
|
||||
decltype(auto) base = it.base();
|
||||
static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
|
||||
assert(base == &t);
|
||||
|
|
@ -55,7 +57,7 @@ constexpr bool test() {
|
|||
|
||||
// &&
|
||||
{
|
||||
ElementsIter it{&t};
|
||||
ElementsIter it = ev.begin();
|
||||
decltype(auto) base = std::move(it).base();
|
||||
static_assert(std::is_same_v<decltype(base), std::tuple<int>*>);
|
||||
assert(base == &t);
|
||||
|
|
@ -63,8 +65,8 @@ constexpr bool test() {
|
|||
|
||||
// const &&
|
||||
{
|
||||
const ElementsIter it{&t};
|
||||
decltype(auto) base = std::move(it).base();
|
||||
const ElementsIter it = ev.begin();
|
||||
decltype(auto) base = std::move(it).base();
|
||||
static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
|
||||
assert(base == &t);
|
||||
}
|
||||
|
|
@ -78,10 +80,10 @@ constexpr bool test() {
|
|||
constexpr bool operator==(const MoveOnlyIter&) const { return true; }
|
||||
};
|
||||
|
||||
using MoveOnlyElemIter =
|
||||
std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>>;
|
||||
std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0> mev{
|
||||
std::ranges::subrange{MoveOnlyIter{{}, MoveOnly{5}}, Sent{}}};
|
||||
auto it = mev.begin();
|
||||
|
||||
MoveOnlyElemIter it{MoveOnlyIter{{}, MoveOnly{5}}};
|
||||
decltype(auto) base = std::move(it).base();
|
||||
static_assert(std::is_same_v<decltype(base), MoveOnlyIter>);
|
||||
assert(base.mo.get() == 5);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit iterator(iterator_t<Base> current);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
using BaseIter = std::tuple<int>*;
|
||||
using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<BaseIter, BaseIter>, 0>>;
|
||||
|
||||
static_assert(!std::is_constructible_v<ElementsIter, BaseIter>);
|
||||
static_assert(!std::is_convertible_v<BaseIter, ElementsIter>);
|
||||
|
|
@ -1,54 +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
|
||||
|
||||
// constexpr explicit iterator(iterator_t<Base> current);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <tuple>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
// Test explicit
|
||||
using BaseIter = std::tuple<int>*;
|
||||
using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<BaseIter, BaseIter>, 0>>;
|
||||
|
||||
static_assert(std::is_constructible_v<ElementsIter, BaseIter>);
|
||||
static_assert(!std::is_convertible_v<BaseIter, ElementsIter>);
|
||||
|
||||
struct TracedMoveIter : IterBase<TracedMoveIter>{
|
||||
bool moved = false;
|
||||
|
||||
constexpr TracedMoveIter() = default;
|
||||
constexpr TracedMoveIter(const TracedMoveIter&) = default;
|
||||
constexpr TracedMoveIter(TracedMoveIter&&) : moved{true} {}
|
||||
constexpr TracedMoveIter& operator=(TracedMoveIter&&) = default;
|
||||
constexpr TracedMoveIter& operator=(const TracedMoveIter&) = default;
|
||||
};
|
||||
|
||||
struct TracedMoveView : std::ranges::view_base {
|
||||
TracedMoveIter begin() const;
|
||||
TracedMoveIter end() const;
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
using Iter = std::ranges::iterator_t<std::ranges::elements_view<TracedMoveView, 0>>;
|
||||
Iter iter{TracedMoveIter{}};
|
||||
assert(iter.base().moved);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -57,8 +57,16 @@ static_assert(!std::is_constructible_v<ConstElemIter<NonConvertibleView>, ElemIt
|
|||
static_assert(!std::is_constructible_v<ElemIter<NonConvertibleView>, ConstElemIter<NonConvertibleView>>);
|
||||
|
||||
constexpr bool test() {
|
||||
ElemIter<ConvertibleView> iter{ConvertibleIter<false>{5}};
|
||||
ConstElemIter<ConvertibleView> constIter = iter; // implicit
|
||||
struct TestRange : std::ranges::view_base {
|
||||
constexpr auto begin() { return ConvertibleIter<false>{5}; }
|
||||
constexpr auto end() { return ConvertibleIter<false>{5}; }
|
||||
constexpr auto begin() const { return ConvertibleIter<true>{5}; }
|
||||
constexpr auto end() const { return ConvertibleIter<true>{5}; }
|
||||
};
|
||||
|
||||
std::ranges::elements_view<TestRange, 0> ev{TestRange{}};
|
||||
ElemIter<TestRange> iter = ev.begin();
|
||||
ConstElemIter<TestRange> constIter = iter; // implicit
|
||||
assert(constIter.base().movedFromOtherConst);
|
||||
assert(constIter.base().i == 5);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include <utility>
|
||||
|
||||
struct Sent {
|
||||
int i;
|
||||
int i = 5;
|
||||
|
||||
friend constexpr bool operator==(std::tuple<int>*, const Sent&) { return true; }
|
||||
};
|
||||
|
|
@ -27,7 +27,8 @@ constexpr bool test() {
|
|||
using EleRange = std::ranges::elements_view<BaseRange, 0>;
|
||||
using EleSent = std::ranges::sentinel_t<EleRange>;
|
||||
|
||||
const EleSent st{Sent{5}};
|
||||
const EleRange ev;
|
||||
const EleSent st = ev.end();
|
||||
std::same_as<Sent> decltype(auto) base = st.base();
|
||||
assert(base.i == 5);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(sentinel_t<Base> end);
|
||||
|
||||
#include <cassert>
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
struct Sent {
|
||||
int i;
|
||||
|
|
@ -26,27 +26,7 @@ struct Range : std::ranges::view_base {
|
|||
Sent end();
|
||||
};
|
||||
|
||||
// Test explicit
|
||||
using ElementsView = std::ranges::elements_view<Range, 0>;
|
||||
|
||||
static_assert(std::is_constructible_v<std::ranges::sentinel_t<std::ranges::elements_view<Range, 0>>, Sent>);
|
||||
static_assert(!std::is_convertible_v<Sent, std::ranges::sentinel_t<std::ranges::elements_view<Range, 0>>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// base is init correctly
|
||||
{
|
||||
using R = std::ranges::elements_view<Range, 0>;
|
||||
using Sentinel = std::ranges::sentinel_t<R>;
|
||||
|
||||
Sentinel s1(Sent{5});
|
||||
assert(s1.base().i == 5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
static_assert(!std::is_constructible_v<std::ranges::sentinel_t<ElementsView>, Sent>);
|
||||
static_assert(!std::is_convertible_v<Sent, std::ranges::sentinel_t<ElementsView>>);
|
||||
|
|
@ -67,12 +67,19 @@ static_assert(
|
|||
constexpr bool test() {
|
||||
// base is init correctly
|
||||
{
|
||||
using R = std::ranges::elements_view<Range, 0>;
|
||||
struct TestRange : std::ranges::view_base {
|
||||
constexpr std::tuple<int>* begin() const { return nullptr; }
|
||||
constexpr Sent end() { return Sent{5}; }
|
||||
constexpr ConstSent end() const { return ConstSent{5}; }
|
||||
};
|
||||
|
||||
using R = std::ranges::elements_view<TestRange, 0>;
|
||||
using Sentinel = std::ranges::sentinel_t<R>;
|
||||
using ConstSentinel = std::ranges::sentinel_t<const R>;
|
||||
static_assert(!std::same_as<Sentinel, ConstSentinel>);
|
||||
|
||||
Sentinel s1(Sent{5});
|
||||
R r{TestRange{}};
|
||||
Sentinel s1 = r.end();
|
||||
ConstSentinel s2 = s1;
|
||||
assert(s2.base().i == 5);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,9 @@ constexpr void test() {
|
|||
|
||||
for (std::ptrdiff_t n = 0; n != 5; ++n) {
|
||||
FilterView view = make_filter_view(array.data(), array.data() + array.size(), AlwaysTrue{});
|
||||
FilterIterator const iter(view, Iter(array.data() + n));
|
||||
FilterIterator iter = view.begin();
|
||||
for (std::ptrdiff_t i = 0; i < n; ++i)
|
||||
++iter;
|
||||
std::same_as<Iter> decltype(auto) result = iter.operator->();
|
||||
assert(base(result) == array.data() + n);
|
||||
assert(iter->x == n);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ constexpr void test() {
|
|||
|
||||
// Test the const& version
|
||||
{
|
||||
FilterIterator const iter(view, Iter(array.data()));
|
||||
FilterIterator const iter = view.begin();
|
||||
Iter const& result = iter.base();
|
||||
ASSERT_SAME_TYPE(Iter const&, decltype(iter.base()));
|
||||
ASSERT_NOEXCEPT(iter.base());
|
||||
|
|
@ -46,7 +46,7 @@ constexpr void test() {
|
|||
|
||||
// Test the && version
|
||||
{
|
||||
FilterIterator iter(view, Iter(array.data()));
|
||||
FilterIterator iter = view.begin();
|
||||
Iter result = std::move(iter).base();
|
||||
ASSERT_SAME_TYPE(Iter, decltype(std::move(iter).base()));
|
||||
assert(base(result) == array.data());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr std::ranges::filter_view::<iterator>(filter_view&, iterator_t<V>);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "../types.h"
|
||||
|
||||
using View = minimal_view<int*, sentinel_wrapper<int*>>;
|
||||
using ViewIter = std::ranges::iterator_t<View>;
|
||||
using FilterView = std::ranges::filter_view<View, AlwaysTrue>;
|
||||
using FilterIterator = std::ranges::iterator_t<FilterView>;
|
||||
|
||||
static_assert(!std::constructible_from<FilterIterator, FilterView&, ViewIter>);
|
||||
|
|
@ -1,51 +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
|
||||
|
||||
// constexpr std::ranges::filter_view::<iterator>(filter_view&, iterator_t<V>);
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include "test_iterators.h"
|
||||
#include "../types.h"
|
||||
|
||||
template <class Iter, class Sent = sentinel_wrapper<Iter>>
|
||||
constexpr void test() {
|
||||
using View = minimal_view<Iter, Sent>;
|
||||
using FilterView = std::ranges::filter_view<View, AlwaysTrue>;
|
||||
using FilterIterator = std::ranges::iterator_t<FilterView>;
|
||||
|
||||
std::array<int, 10> array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
View view(Iter(array.data()), Sent(Iter(array.data() + array.size())));
|
||||
Iter iter = view.begin();
|
||||
|
||||
FilterView filter_view(std::move(view), AlwaysTrue{});
|
||||
FilterIterator filter_iter(filter_view, std::move(iter));
|
||||
assert(base(filter_iter.base()) == array.data());
|
||||
}
|
||||
|
||||
constexpr bool tests() {
|
||||
test<cpp17_input_iterator<int*>>();
|
||||
test<cpp20_input_iterator<int*>>();
|
||||
test<forward_iterator<int*>>();
|
||||
test<bidirectional_iterator<int*>>();
|
||||
test<random_access_iterator<int*>>();
|
||||
test<contiguous_iterator<int*>>();
|
||||
test<int*>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
tests();
|
||||
static_assert(tests());
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -36,7 +36,9 @@ constexpr void test() {
|
|||
FilterView view = make_filter_view(array.data(), array.data() + array.size(), AlwaysTrue{});
|
||||
|
||||
for (std::size_t n = 0; n != array.size(); ++n) {
|
||||
FilterIterator const iter(view, Iter(array.data() + n));
|
||||
FilterIterator iter = view.begin();
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
++iter;
|
||||
ValueType& result = *iter;
|
||||
ASSERT_SAME_TYPE(ValueType&, decltype(*iter));
|
||||
assert(&result == array.data() + n);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(filter_view&);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "../types.h"
|
||||
|
||||
using View = minimal_view<int*, sentinel_wrapper<int*>>;
|
||||
using FilterView = std::ranges::filter_view<View, AlwaysTrue>;
|
||||
using FilterSentinel = std::ranges::sentinel_t<FilterView>;
|
||||
|
||||
static_assert(!std::constructible_from<FilterSentinel, FilterView>);
|
||||
static_assert(!std::convertible_to<FilterView, FilterSentinel>);
|
||||
|
|
@ -1,60 +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
|
||||
|
||||
// constexpr explicit sentinel(filter_view&);
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "test_iterators.h"
|
||||
#include "../types.h"
|
||||
|
||||
template <class Iter, class Sent = sentinel_wrapper<Iter>>
|
||||
constexpr void test() {
|
||||
using View = minimal_view<Iter, Sent>;
|
||||
using FilterView = std::ranges::filter_view<View, AlwaysTrue>;
|
||||
using FilterSentinel = std::ranges::sentinel_t<FilterView>;
|
||||
|
||||
auto make_filter_view = [](auto begin, auto end, auto pred) {
|
||||
View view{Iter(begin), Sent(Iter(end))};
|
||||
return FilterView(std::move(view), pred);
|
||||
};
|
||||
|
||||
std::array<int, 5> array{0, 1, 2, 3, 4};
|
||||
FilterView view = make_filter_view(array.data(), array.data() + array.size(), AlwaysTrue{});
|
||||
|
||||
FilterSentinel sent(view);
|
||||
assert(base(base(sent.base())) == base(base(view.end().base())));
|
||||
|
||||
static_assert(!std::is_constructible_v<FilterSentinel, FilterView const&>);
|
||||
static_assert(!std::is_constructible_v<FilterSentinel, FilterView>);
|
||||
static_assert( std::is_constructible_v<FilterSentinel, FilterView&> &&
|
||||
!std::is_convertible_v<FilterView&, FilterSentinel>);
|
||||
}
|
||||
|
||||
constexpr bool tests() {
|
||||
test<cpp17_input_iterator<int*>>();
|
||||
test<cpp20_input_iterator<int*>>();
|
||||
test<forward_iterator<int*>>();
|
||||
test<bidirectional_iterator<int*>>();
|
||||
test<random_access_iterator<int*>>();
|
||||
test<contiguous_iterator<int*>>();
|
||||
test<int*>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
tests();
|
||||
static_assert(tests());
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(Parent& parent);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
using Parent = std::ranges::join_view<ParentView<ChildView>>;
|
||||
static_assert(!std::is_constructible_v<std::ranges::sentinel_t<Parent>, Parent&>);
|
||||
static_assert(!std::is_convertible_v<std::ranges::sentinel_t<Parent>, Parent&>);
|
||||
|
|
@ -1,43 +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
|
||||
|
||||
// constexpr explicit sentinel(Parent& parent);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
CopyableParent parent{children};
|
||||
std::ranges::join_view jv(parent);
|
||||
std::ranges::sentinel_t<decltype(jv)> sent(jv);
|
||||
assert(sent == std::ranges::next(jv.begin(), 16));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
{
|
||||
// Test explicitness.
|
||||
using Parent = std::ranges::join_view<ParentView<ChildView>>;
|
||||
static_assert( std::is_constructible_v<std::ranges::sentinel_t<Parent>, Parent&>);
|
||||
static_assert(!std::is_convertible_v<std::ranges::sentinel_t<Parent>, Parent&>);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit inner-iterator::inner-iterator(outer-iterator<Const> i);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
static_assert(!std::is_constructible_v<InnerIterConst, OuterIterConst>);
|
||||
static_assert(!std::is_convertible_v<InnerIterConst, OuterIterConst>);
|
||||
|
||||
static_assert(!std::is_constructible_v<InnerIterNonConst, OuterIterNonConst>);
|
||||
static_assert(!std::is_convertible_v<InnerIterNonConst, OuterIterNonConst>);
|
||||
|
|
@ -1,43 +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
|
||||
|
||||
// constexpr explicit inner-iterator::inner-iterator(outer-iterator<Const> i);
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
static_assert(!std::is_constructible_v<InnerIterNonConst, OuterIterConst>);
|
||||
|
||||
template <class Inner, class Outer>
|
||||
constexpr void test_impl() {
|
||||
[[maybe_unused]] Inner i(Outer{});
|
||||
// Verify that the constructor is `explicit`.
|
||||
static_assert(!std::is_convertible_v<Outer, Inner>);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_impl<InnerIterForward, OuterIterForward>();
|
||||
test_impl<InnerIterInput, OuterIterInput>();
|
||||
// Is only constructible if both the outer and the inner iterators have the same constness.
|
||||
test_impl<InnerIterConst, OuterIterConst>();
|
||||
// Note: this works because of an implicit conversion (`OuterIterNonConst` is converted to `OuterIterConst`).
|
||||
test_impl<InnerIterConst, OuterIterNonConst>();
|
||||
test_impl<InnerIterNonConst, OuterIterNonConst>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -6,31 +6,17 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr outer-iterator(Parent& parent, iterator_t<Base> current);
|
||||
// requires forward_range<Base>
|
||||
|
||||
#include <ranges>
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
static_assert(!std::ranges::forward_range<SplitViewInput>);
|
||||
static_assert(!std::is_constructible_v<OuterIterInput, SplitViewInput&, std::ranges::iterator_t<InputView>>);
|
||||
|
||||
constexpr bool test() {
|
||||
ForwardView input("abc");
|
||||
SplitViewForward v(std::move(input), " ");
|
||||
[[maybe_unused]] OuterIterForward i(v, input.begin());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
static_assert(std::ranges::forward_range<SplitViewForward>);
|
||||
static_assert(!std::is_constructible_v<OuterIterForward, SplitViewForward&, std::ranges::iterator_t<ForwardView>>);
|
||||
|
|
@ -6,34 +6,18 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// explicit std::ranges::lazy_split_view::outer-iterator::outer-iterator(Parent& parent)
|
||||
// requires (!forward_range<Base>)
|
||||
|
||||
#include <ranges>
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
// Verify that the constructor is `explicit`.
|
||||
static_assert(!std::ranges::forward_range<SplitViewInput>);
|
||||
static_assert(!std::is_constructible_v<OuterIterInput, SplitViewInput&>);
|
||||
static_assert(!std::is_convertible_v<SplitViewInput&, OuterIterInput>);
|
||||
|
||||
static_assert( std::ranges::forward_range<SplitViewForward>);
|
||||
static_assert(!std::is_constructible_v<OuterIterForward, SplitViewForward&>);
|
||||
|
||||
constexpr bool test() {
|
||||
InputView input;
|
||||
SplitViewInput v(input, ForwardTinyView());
|
||||
[[maybe_unused]] OuterIterInput i(v);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -16,9 +16,20 @@
|
|||
#include "../types.h"
|
||||
|
||||
struct Iter : ForwardIterBase<Iter> {
|
||||
int i;
|
||||
int i = 0;
|
||||
constexpr Iter() = default;
|
||||
constexpr Iter(int ii) : i(ii) {}
|
||||
constexpr int operator*() const { return i; }
|
||||
constexpr Iter& operator++() {
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
constexpr Iter operator++(int) {
|
||||
Iter tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
friend constexpr bool operator==(const Iter& x, const Iter& y) { return x.i == y.i; }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
|
|
@ -26,34 +37,32 @@ constexpr bool test() {
|
|||
using SplitView = std::ranges::split_view<std::ranges::subrange<Iter>, std::ranges::subrange<Iter>>;
|
||||
using SplitIter = std::ranges::iterator_t<SplitView>;
|
||||
|
||||
SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}}, std::ranges::subrange<Iter>{Iter{8}, Iter{9}}};
|
||||
|
||||
// const &
|
||||
{
|
||||
SplitView sv;
|
||||
const SplitIter it{sv, Iter{5}, {}};
|
||||
const SplitIter it = sv.begin();
|
||||
std::same_as<Iter> decltype(auto) base = it.base();
|
||||
assert(base.i == 5);
|
||||
}
|
||||
|
||||
// &
|
||||
{
|
||||
SplitView sv;
|
||||
SplitIter it{sv, Iter{5}, {}};
|
||||
SplitIter it = sv.begin();
|
||||
std::same_as<Iter> decltype(auto) base = it.base();
|
||||
assert(base.i == 5);
|
||||
}
|
||||
|
||||
// &&
|
||||
{
|
||||
SplitView sv;
|
||||
SplitIter it{sv, Iter{5}, {}};
|
||||
SplitIter it = sv.begin();
|
||||
std::same_as<Iter> decltype(auto) base = std::move(it).base();
|
||||
assert(base.i == 5);
|
||||
}
|
||||
|
||||
// const &&
|
||||
{
|
||||
SplitView sv;
|
||||
const SplitIter it{sv, Iter{5}, {}};
|
||||
const SplitIter it = sv.begin();
|
||||
std::same_as<Iter> decltype(auto) base = std::move(it).base();
|
||||
assert(base.i == 5);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
|
||||
|
||||
#include <cassert>
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
|
|
@ -30,24 +32,7 @@ struct TracedMoveView : std::ranges::view_base {
|
|||
constexpr TracedMoveIter end() const { return {}; }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
using SplitView = std::ranges::split_view<TracedMoveView, TracedMoveView>;
|
||||
using SplitIter = std::ranges::iterator_t<SplitView>;
|
||||
using SplitView = std::ranges::split_view<TracedMoveView, TracedMoveView>;
|
||||
using SplitIter = std::ranges::iterator_t<SplitView>;
|
||||
|
||||
SplitView sv{TracedMoveView{}, TracedMoveView{}};
|
||||
SplitIter iter = {sv, sv.base().begin(), std::ranges::subrange<TracedMoveIter>{sv.base().begin(), sv.base().end()}};
|
||||
assert(iter.base().moved);
|
||||
|
||||
auto subRange = *iter;
|
||||
assert(subRange.begin().moved);
|
||||
assert(subRange.end().moved);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
static_assert(!std::is_constructible_v<SplitIter, SplitView, TracedMoveIter, std::ranges::subrange<TracedMoveIter>>);
|
||||
|
|
@ -17,24 +17,31 @@
|
|||
#include "../types.h"
|
||||
|
||||
struct Iter : ForwardIterBase<Iter> {
|
||||
int i;
|
||||
int i = 0;
|
||||
constexpr Iter() = default;
|
||||
constexpr Iter(int ii) : i(ii) {}
|
||||
constexpr int operator*() const { return i; }
|
||||
constexpr Iter& operator++() {
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
constexpr Iter operator++(int) {
|
||||
Iter tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
friend constexpr bool operator==(const Iter& x, const Iter& y) { return x.i == y.i; }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
using SplitView = std::ranges::split_view<std::ranges::subrange<Iter>, std::ranges::subrange<Iter>>;
|
||||
using SplitIter = std::ranges::iterator_t<SplitView>;
|
||||
|
||||
{
|
||||
SplitView sv;
|
||||
Iter current{5};
|
||||
std::ranges::subrange next{Iter{6}, Iter{7}};
|
||||
const SplitIter it{sv, current, next};
|
||||
std::same_as<std::ranges::subrange<Iter>> decltype(auto) value = *it;
|
||||
assert(value.begin().i == 5);
|
||||
assert(value.end().i == 6);
|
||||
}
|
||||
SplitView sv{std::ranges::subrange<Iter>{Iter{5}, Iter{8}}, std::ranges::subrange<Iter>{Iter{7}, Iter{8}}};
|
||||
const SplitIter it = sv.begin();
|
||||
std::same_as<std::ranges::subrange<Iter>> decltype(auto) value = *it;
|
||||
assert(value.begin().i == 5);
|
||||
assert(value.end().i == 7);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,44 +6,19 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(split_view& parent);
|
||||
|
||||
#include <cassert>
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "../types.h"
|
||||
|
||||
// test explicit
|
||||
using Range = std::ranges::subrange<int*, sentinel_wrapper<int*>>;
|
||||
using SplitView = std::ranges::split_view<Range, std::ranges::single_view<int>>;
|
||||
using SplitSent = std::ranges::sentinel_t<SplitView>;
|
||||
|
||||
static_assert(std::is_constructible_v<SplitSent, SplitView&>);
|
||||
static_assert(!std::is_constructible_v<SplitSent, SplitView&>);
|
||||
static_assert(!std::is_convertible_v<SplitView&, SplitSent>);
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
int buffer[] = {0, 1, 2};
|
||||
Range input{buffer, sentinel_wrapper<int*>(buffer + 3)};
|
||||
SplitView sv(input, -1);
|
||||
auto it = sv.begin();
|
||||
|
||||
SplitSent sent(sv);
|
||||
assert(sent != it);
|
||||
|
||||
++it;
|
||||
assert(sent == it);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,86 +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
|
||||
|
||||
// constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
struct Sent {
|
||||
int i;
|
||||
|
||||
friend constexpr bool operator==(int* iter, const Sent& s) { return s.i > *iter; }
|
||||
};
|
||||
|
||||
struct Range : std::ranges::view_base {
|
||||
int* begin() const;
|
||||
Sent end();
|
||||
};
|
||||
|
||||
struct Pred {
|
||||
bool operator()(int i) const;
|
||||
};
|
||||
|
||||
// Test explicit
|
||||
template <class T>
|
||||
void conversion_test(T);
|
||||
|
||||
template <class T, class... Args>
|
||||
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
|
||||
static_assert(ImplicitlyConstructible<int, int>);
|
||||
|
||||
static_assert(std::is_constructible_v<std::ranges::sentinel_t<std::ranges::take_while_view<Range, Pred>>,
|
||||
std::ranges::sentinel_t<Range>,
|
||||
const Pred*>);
|
||||
static_assert(!ImplicitlyConstructible<std::ranges::sentinel_t<std::ranges::take_while_view<Range, Pred>>,
|
||||
std::ranges::sentinel_t<Range>,
|
||||
const Pred*>);
|
||||
|
||||
constexpr bool test() {
|
||||
// base is init correctly
|
||||
{
|
||||
using R = std::ranges::take_while_view<Range, bool (*)(int)>;
|
||||
using Sentinel = std::ranges::sentinel_t<R>;
|
||||
|
||||
Sentinel s1(Sent{5}, nullptr);
|
||||
assert(s1.base().i == 5);
|
||||
}
|
||||
|
||||
// pred is init correctly
|
||||
{
|
||||
bool called = false;
|
||||
auto pred = [&](int) {
|
||||
called = true;
|
||||
return false;
|
||||
};
|
||||
|
||||
using R = std::ranges::take_while_view<Range, decltype(pred)>;
|
||||
using Sentinel = std::ranges::sentinel_t<R>;
|
||||
|
||||
int i = 10;
|
||||
int* iter = &i;
|
||||
Sentinel s(Sent{0}, &pred);
|
||||
|
||||
bool b = iter == s;
|
||||
assert(called);
|
||||
assert(b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
struct Sent {
|
||||
int i;
|
||||
|
||||
friend constexpr bool operator==(int* iter, const Sent& s) { return s.i > *iter; }
|
||||
};
|
||||
|
||||
struct Range : std::ranges::view_base {
|
||||
int* begin() const;
|
||||
Sent end();
|
||||
};
|
||||
|
||||
struct Pred {
|
||||
bool operator()(int i) const;
|
||||
};
|
||||
|
||||
using Sentinel = std::ranges::sentinel_t<std::ranges::take_while_view<Range, Pred>>;
|
||||
|
||||
static_assert(!std::is_constructible_v<Sentinel, std::ranges::sentinel_t<Range>, const Pred*>);
|
||||
|
|
@ -70,34 +70,48 @@ static_assert(!std::is_constructible_v<
|
|||
constexpr bool test() {
|
||||
// base is init correctly
|
||||
{
|
||||
using R = std::ranges::take_while_view<Range, bool (*)(int)>;
|
||||
struct TestRng : std::ranges::view_base {
|
||||
constexpr int* begin() const { return nullptr; }
|
||||
constexpr Sent end() { return Sent{5}; }
|
||||
constexpr ConstSent end() const { return ConstSent{5}; }
|
||||
};
|
||||
|
||||
using R = std::ranges::take_while_view<TestRng, bool (*)(int)>;
|
||||
using Sentinel = std::ranges::sentinel_t<R>;
|
||||
using ConstSentinel = std::ranges::sentinel_t<const R>;
|
||||
static_assert(!std::same_as<Sentinel, ConstSentinel>);
|
||||
|
||||
Sentinel s1(Sent{5}, nullptr);
|
||||
R r{TestRng{}, nullptr};
|
||||
Sentinel s1 = r.end();
|
||||
ConstSentinel s2 = s1;
|
||||
assert(s2.base().i == 5);
|
||||
}
|
||||
|
||||
// pred is init correctly
|
||||
{
|
||||
struct TestRng : std::ranges::view_base {
|
||||
constexpr int* begin() const { return nullptr; }
|
||||
constexpr Sent end() { return Sent{0}; }
|
||||
constexpr ConstSent end() const { return ConstSent{0}; }
|
||||
};
|
||||
|
||||
bool called = false;
|
||||
auto pred = [&](int) {
|
||||
called = true;
|
||||
return false;
|
||||
};
|
||||
|
||||
using R = std::ranges::take_while_view<Range, decltype(pred)>;
|
||||
using R = std::ranges::take_while_view<TestRng, decltype(pred)>;
|
||||
using Sentinel = std::ranges::sentinel_t<R>;
|
||||
using ConstSentinel = std::ranges::sentinel_t<const R>;
|
||||
static_assert(!std::same_as<Sentinel, ConstSentinel>);
|
||||
|
||||
int i = 10;
|
||||
int* iter = &i;
|
||||
Sentinel s1(Sent{0}, &pred);
|
||||
R r{TestRng{}, pred};
|
||||
Sentinel s1 = r.end();
|
||||
ConstSentinel s2 = s1;
|
||||
|
||||
int i = 10;
|
||||
int* iter = &i;
|
||||
[[maybe_unused]] bool b = iter == s2;
|
||||
assert(called);
|
||||
}
|
||||
|
|
@ -111,20 +125,25 @@ constexpr bool test() {
|
|||
constexpr bool operator==(int* iter) const { return i > *iter; }
|
||||
};
|
||||
|
||||
struct Rng : std::ranges::view_base {
|
||||
int* begin() const;
|
||||
Sent end();
|
||||
MoveOnlyConvert end() const;
|
||||
struct TestPred {
|
||||
constexpr bool operator()(int) const { return false; }
|
||||
};
|
||||
|
||||
using R = std::ranges::take_while_view<Rng, Pred>;
|
||||
struct Rng : std::ranges::view_base {
|
||||
constexpr int* begin() const { return nullptr; }
|
||||
constexpr Sent end() { return Sent{0}; }
|
||||
constexpr MoveOnlyConvert end() const { return MoveOnlyConvert(Sent{0}); }
|
||||
};
|
||||
|
||||
using R = std::ranges::take_while_view<Rng, TestPred>;
|
||||
using Sentinel = std::ranges::sentinel_t<R>;
|
||||
using ConstSentinel = std::ranges::sentinel_t<const R>;
|
||||
static_assert(!std::same_as<Sentinel, ConstSentinel>);
|
||||
|
||||
Sentinel s1(Sent{5}, nullptr);
|
||||
R r{Rng{}, TestPred{}};
|
||||
Sentinel s1 = r.end();
|
||||
ConstSentinel s2 = s1;
|
||||
assert(s2.base().i == 5);
|
||||
assert(s2.base().i == 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(sentinel_t<Base> end);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "../types.h"
|
||||
|
||||
using TakeView = std::ranges::take_view<MoveOnlyView>;
|
||||
using Sentinel = std::ranges::sentinel_t<TakeView>;
|
||||
|
||||
static_assert(!std::is_constructible_v<Sentinel, sentinel_wrapper<int*>>);
|
||||
static_assert(!std::is_convertible_v<sentinel_wrapper<int*>, Sentinel>);
|
||||
|
|
@ -9,7 +9,6 @@
|
|||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// sentinel() = default;
|
||||
// constexpr explicit sentinel(sentinel_t<Base> end);
|
||||
// constexpr sentinel(sentinel<!Const> s)
|
||||
// requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
|
||||
|
||||
|
|
@ -49,18 +48,6 @@ constexpr bool test() {
|
|||
assert(std::as_const(tv).begin() + 4 == cs);
|
||||
}
|
||||
|
||||
{
|
||||
// Test the constructor from "base-sentinel" to "sentinel".
|
||||
using TakeView = std::ranges::take_view<MoveOnlyView>;
|
||||
using Sentinel = std::ranges::sentinel_t<TakeView>;
|
||||
sentinel_wrapper<int*> sw1 = MoveOnlyView(buffer).end();
|
||||
static_assert(std::is_constructible_v<Sentinel, sentinel_wrapper<int*>>);
|
||||
static_assert(!std::is_convertible_v<sentinel_wrapper<int*>, Sentinel>);
|
||||
auto s = Sentinel(sw1);
|
||||
std::same_as<sentinel_wrapper<int*>> auto sw2 = s.base();
|
||||
assert(base(sw2) == base(sw1));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr iterator(Parent& parent, iterator_t<Base> current);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
using TransformView = std::ranges::transform_view<MoveOnlyView, PlusOne>;
|
||||
using TransformViewBaseIter = std::ranges::iterator_t<MoveOnlyView>;
|
||||
using TransformIter = std::ranges::iterator_t<TransformView>;
|
||||
|
||||
static_assert(!std::is_constructible_v<TransformIter, TransformView&, TransformViewBaseIter>);
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(sentinel_t<Base> end);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "../types.h"
|
||||
|
||||
using BaseSent = std::ranges::sentinel_t<SizedSentinelView>;
|
||||
using TransformView = std::ranges::transform_view<SizedSentinelView, PlusOne>;
|
||||
using TransformSent = std::ranges::sentinel_t<TransformView>;
|
||||
|
||||
static_assert(!std::is_constructible_v<TransformSent, BaseSent>);
|
||||
static_assert(!std::is_convertible_v<BaseSent, TransformSent>);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit iterator(W value);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
static_assert(!std::is_constructible_v<std::ranges::iterator_t<std::ranges::iota_view<int>>, int>);
|
||||
|
||||
using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
|
||||
static_assert(!std::is_constructible_v<Iter, SomeInt>);
|
||||
static_assert(!std::is_convertible_v<SomeInt, Iter>);
|
||||
|
|
@ -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
|
||||
|
||||
// constexpr explicit iterator(W value);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
using Iter = std::ranges::iterator_t<std::ranges::iota_view<int>>;
|
||||
auto iter = Iter(42);
|
||||
assert(*iter == 42);
|
||||
}
|
||||
{
|
||||
using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
|
||||
auto iter = Iter(SomeInt(42));
|
||||
assert(*iter == SomeInt(42));
|
||||
}
|
||||
{
|
||||
using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
|
||||
static_assert(!std::is_convertible_v<Iter, SomeInt>);
|
||||
static_assert( std::is_constructible_v<Iter, SomeInt>);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// constexpr explicit sentinel(Bound bound);
|
||||
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
|
||||
static_assert(!std::is_constructible_v<Sent, IntSentinelWith<SomeInt>>);
|
||||
static_assert(!std::is_convertible_v<IntSentinelWith<SomeInt>, Sent>);
|
||||
|
|
@ -1,47 +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
|
||||
|
||||
// constexpr explicit sentinel(Bound bound);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<int, IntSentinelWith<int>>>;
|
||||
using Iter = std::ranges::iterator_t<std::ranges::iota_view<int, IntSentinelWith<int>>>;
|
||||
auto sent = Sent(IntSentinelWith<int>(42));
|
||||
assert(sent == Iter(42));
|
||||
}
|
||||
{
|
||||
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
|
||||
using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
|
||||
auto sent = Sent(IntSentinelWith<SomeInt>(SomeInt(42)));
|
||||
assert(sent == Iter(SomeInt(42)));
|
||||
}
|
||||
{
|
||||
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
|
||||
static_assert(!std::is_convertible_v<Sent, IntSentinelWith<SomeInt>>);
|
||||
static_assert( std::is_constructible_v<Sent, IntSentinelWith<SomeInt>>);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -39,10 +39,9 @@ void test() {
|
|||
|
||||
// LWG 3568. basic_istream_view needs to initialize value_
|
||||
{
|
||||
auto iss = make_string_stream<CharT>("123");
|
||||
auto iss = make_string_stream<CharT>("");
|
||||
std::ranges::basic_istream_view<int, CharT> isv{iss};
|
||||
using Iter = std::ranges::iterator_t<decltype(isv)>;
|
||||
Iter iter{isv};
|
||||
auto iter = isv.begin();
|
||||
assert(*iter == 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++20
|
||||
// UNSUPPORTED: no-localization
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr explicit iterator(basic_istream_view& parent) noexcept;
|
||||
|
||||
#include <cassert>
|
||||
// The constructor is now `private` (exposition-only) per P3059R2.
|
||||
|
||||
#include <ranges>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../utils.h"
|
||||
|
||||
// test that the constructor is explicit
|
||||
template <class CharT>
|
||||
|
|
@ -25,34 +25,10 @@ using IstreamView = std::ranges::basic_istream_view<int, CharT>;
|
|||
template <class CharT>
|
||||
using Iter = std::ranges::iterator_t<IstreamView<CharT>>;
|
||||
|
||||
static_assert(std::constructible_from<Iter<char>, IstreamView<char>&>);
|
||||
static_assert(!std::constructible_from<Iter<char>, IstreamView<char>&>);
|
||||
static_assert(!std::convertible_to<IstreamView<char>&, Iter<char>>);
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
static_assert(std::constructible_from<Iter<wchar_t>, IstreamView<wchar_t>&>);
|
||||
static_assert(!std::constructible_from<Iter<wchar_t>, IstreamView<wchar_t>&>);
|
||||
static_assert(!std::convertible_to<IstreamView<wchar_t>&, Iter<wchar_t>>);
|
||||
#endif
|
||||
|
||||
// test that the constructor is noexcept
|
||||
static_assert(std::is_nothrow_constructible_v<Iter<char>, IstreamView<char>&>);
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
static_assert(std::is_nothrow_constructible_v<Iter<wchar_t>, IstreamView<wchar_t>&>);
|
||||
#endif
|
||||
|
||||
template <class CharT>
|
||||
void test() {
|
||||
auto iss = make_string_stream<CharT>("123");
|
||||
std::ranges::basic_istream_view<int, CharT> isv{iss};
|
||||
Iter<CharT> it{isv};
|
||||
++it;
|
||||
assert(*it == 123);
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<char>();
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -35,8 +35,8 @@ void test() {
|
|||
std::ranges::basic_istream_view<int, CharT> isv{iss};
|
||||
using Iter = std::ranges::iterator_t<decltype(isv)>;
|
||||
|
||||
Iter it1{isv};
|
||||
Iter it2{isv};
|
||||
Iter it1 = isv.begin();
|
||||
Iter it2 = isv.begin();
|
||||
assert(&*it1 == &*it2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue