Path: blob/main/contrib/llvm-project/libcxx/include/__ranges/iota_view.h
35235 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___RANGES_IOTA_VIEW_H10#define _LIBCPP___RANGES_IOTA_VIEW_H1112#include <__assert>13#include <__compare/three_way_comparable.h>14#include <__concepts/arithmetic.h>15#include <__concepts/constructible.h>16#include <__concepts/convertible_to.h>17#include <__concepts/copyable.h>18#include <__concepts/equality_comparable.h>19#include <__concepts/invocable.h>20#include <__concepts/same_as.h>21#include <__concepts/semiregular.h>22#include <__concepts/totally_ordered.h>23#include <__config>24#include <__iterator/concepts.h>25#include <__iterator/incrementable_traits.h>26#include <__iterator/iterator_traits.h>27#include <__iterator/unreachable_sentinel.h>28#include <__ranges/enable_borrowed_range.h>29#include <__ranges/movable_box.h>30#include <__ranges/view_interface.h>31#include <__type_traits/conditional.h>32#include <__type_traits/is_nothrow_constructible.h>33#include <__type_traits/make_unsigned.h>34#include <__type_traits/type_identity.h>35#include <__utility/forward.h>36#include <__utility/move.h>3738#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)39# pragma GCC system_header40#endif4142_LIBCPP_PUSH_MACROS43#include <__undef_macros>4445_LIBCPP_BEGIN_NAMESPACE_STD4647#if _LIBCPP_STD_VER >= 204849namespace ranges {50template <class _Int>51struct __get_wider_signed {52consteval static auto __call() {53if constexpr (sizeof(_Int) < sizeof(short))54return type_identity<short>{};55else if constexpr (sizeof(_Int) < sizeof(int))56return type_identity<int>{};57else if constexpr (sizeof(_Int) < sizeof(long))58return type_identity<long>{};59else60return type_identity<long long>{};6162static_assert(63sizeof(_Int) <= sizeof(long long), "Found integer-like type that is bigger than largest integer like type.");64}6566using type = typename decltype(__call())::type;67};6869template <class _Start>70using _IotaDiffT =71typename _If< (!integral<_Start> || sizeof(iter_difference_t<_Start>) > sizeof(_Start)),72type_identity<iter_difference_t<_Start>>,73__get_wider_signed<_Start> >::type;7475template <class _Iter>76concept __decrementable = incrementable<_Iter> && requires(_Iter __i) {77{ --__i } -> same_as<_Iter&>;78{ __i-- } -> same_as<_Iter>;79};8081template <class _Iter>82concept __advanceable =83__decrementable<_Iter> && totally_ordered<_Iter> &&84requires(_Iter __i, const _Iter __j, const _IotaDiffT<_Iter> __n) {85{ __i += __n } -> same_as<_Iter&>;86{ __i -= __n } -> same_as<_Iter&>;87_Iter(__j + __n);88_Iter(__n + __j);89_Iter(__j - __n);90{ __j - __j } -> convertible_to<_IotaDiffT<_Iter>>;91};9293template <class>94struct __iota_iterator_category {};9596template <incrementable _Tp>97struct __iota_iterator_category<_Tp> {98using iterator_category = input_iterator_tag;99};100101template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_sentinel_t>102requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start>103class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {104struct __iterator : public __iota_iterator_category<_Start> {105friend class iota_view;106107using iterator_concept =108_If<__advanceable<_Start>,109random_access_iterator_tag,110_If<__decrementable<_Start>,111bidirectional_iterator_tag,112_If<incrementable<_Start>,113forward_iterator_tag,114/*Else*/ input_iterator_tag>>>;115116using value_type = _Start;117using difference_type = _IotaDiffT<_Start>;118119_Start __value_ = _Start();120121_LIBCPP_HIDE_FROM_ABI __iterator()122requires default_initializable<_Start>123= default;124125_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {}126127_LIBCPP_HIDE_FROM_ABI constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) {128return __value_;129}130131_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {132++__value_;133return *this;134}135136_LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }137138_LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int)139requires incrementable<_Start>140{141auto __tmp = *this;142++*this;143return __tmp;144}145146_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--()147requires __decrementable<_Start>148{149--__value_;150return *this;151}152153_LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int)154requires __decrementable<_Start>155{156auto __tmp = *this;157--*this;158return __tmp;159}160161_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n)162requires __advanceable<_Start>163{164if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {165if (__n >= difference_type(0)) {166__value_ += static_cast<_Start>(__n);167} else {168__value_ -= static_cast<_Start>(-__n);169}170} else {171__value_ += __n;172}173return *this;174}175176_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n)177requires __advanceable<_Start>178{179if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {180if (__n >= difference_type(0)) {181__value_ -= static_cast<_Start>(__n);182} else {183__value_ += static_cast<_Start>(-__n);184}185} else {186__value_ -= __n;187}188return *this;189}190191_LIBCPP_HIDE_FROM_ABI constexpr _Start operator[](difference_type __n) const192requires __advanceable<_Start>193{194return _Start(__value_ + __n);195}196197_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)198requires equality_comparable<_Start>199{200return __x.__value_ == __y.__value_;201}202203_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)204requires totally_ordered<_Start>205{206return __x.__value_ < __y.__value_;207}208209_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)210requires totally_ordered<_Start>211{212return __y < __x;213}214215_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)216requires totally_ordered<_Start>217{218return !(__y < __x);219}220221_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)222requires totally_ordered<_Start>223{224return !(__x < __y);225}226227_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)228requires totally_ordered<_Start> && three_way_comparable<_Start>229{230return __x.__value_ <=> __y.__value_;231}232233_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n)234requires __advanceable<_Start>235{236__i += __n;237return __i;238}239240_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i)241requires __advanceable<_Start>242{243return __i + __n;244}245246_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n)247requires __advanceable<_Start>248{249__i -= __n;250return __i;251}252253_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)254requires __advanceable<_Start>255{256if constexpr (__integer_like<_Start>) {257if constexpr (__signed_integer_like<_Start>) {258return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_));259}260if (__y.__value_ > __x.__value_) {261return difference_type(-difference_type(__y.__value_ - __x.__value_));262}263return difference_type(__x.__value_ - __y.__value_);264}265return __x.__value_ - __y.__value_;266}267};268269struct __sentinel {270friend class iota_view;271272private:273_BoundSentinel __bound_sentinel_ = _BoundSentinel();274275public:276_LIBCPP_HIDE_FROM_ABI __sentinel() = default;277_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_BoundSentinel __bound_sentinel)278: __bound_sentinel_(std::move(__bound_sentinel)) {}279280_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {281return __x.__value_ == __y.__bound_sentinel_;282}283284_LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_Start>285operator-(const __iterator& __x, const __sentinel& __y)286requires sized_sentinel_for<_BoundSentinel, _Start>287{288return __x.__value_ - __y.__bound_sentinel_;289}290291_LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_Start>292operator-(const __sentinel& __x, const __iterator& __y)293requires sized_sentinel_for<_BoundSentinel, _Start>294{295return -(__y - __x);296}297};298299_Start __value_ = _Start();300_BoundSentinel __bound_sentinel_ = _BoundSentinel();301302public:303_LIBCPP_HIDE_FROM_ABI iota_view()304requires default_initializable<_Start>305= default;306307_LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(_Start __value) : __value_(std::move(__value)) {}308309_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23310iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel)311: __value_(std::move(__value)), __bound_sentinel_(std::move(__bound_sentinel)) {312// Validate the precondition if possible.313if constexpr (totally_ordered_with<_Start, _BoundSentinel>) {314_LIBCPP_ASSERT_VALID_INPUT_RANGE(315bool(__value_ <= __bound_sentinel_), "iota_view: bound must be reachable from value");316}317}318319_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __iterator __last)320requires same_as<_Start, _BoundSentinel>321: iota_view(std::move(__first.__value_), std::move(__last.__value_)) {}322323_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, _BoundSentinel __last)324requires same_as<_BoundSentinel, unreachable_sentinel_t>325: iota_view(std::move(__first.__value_), std::move(__last)) {}326327_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __sentinel __last)328requires(!same_as<_Start, _BoundSentinel> && !same_as<_BoundSentinel, unreachable_sentinel_t>)329: iota_view(std::move(__first.__value_), std::move(__last.__bound_sentinel_)) {}330331_LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator{__value_}; }332333_LIBCPP_HIDE_FROM_ABI constexpr auto end() const {334if constexpr (same_as<_BoundSentinel, unreachable_sentinel_t>)335return unreachable_sentinel;336else337return __sentinel{__bound_sentinel_};338}339340_LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const341requires same_as<_Start, _BoundSentinel>342{343return __iterator{__bound_sentinel_};344}345346_LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __value_ == __bound_sentinel_; }347348_LIBCPP_HIDE_FROM_ABI constexpr auto size() const349requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||350(integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>351{352if constexpr (__integer_like<_Start> && __integer_like<_BoundSentinel>) {353return (__value_ < 0)354? ((__bound_sentinel_ < 0)355? std::__to_unsigned_like(-__value_) - std::__to_unsigned_like(-__bound_sentinel_)356: std::__to_unsigned_like(__bound_sentinel_) + std::__to_unsigned_like(-__value_))357: std::__to_unsigned_like(__bound_sentinel_) - std::__to_unsigned_like(__value_);358} else {359return std::__to_unsigned_like(__bound_sentinel_ - __value_);360}361}362};363364template <class _Start, class _BoundSentinel>365requires(!__integer_like<_Start> || !__integer_like<_BoundSentinel> ||366(__signed_integer_like<_Start> == __signed_integer_like<_BoundSentinel>))367iota_view(_Start, _BoundSentinel) -> iota_view<_Start, _BoundSentinel>;368369template <class _Start, class _BoundSentinel>370inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true;371372namespace views {373namespace __iota {374struct __fn {375template <class _Start>376_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Start&& __start) const377noexcept(noexcept(ranges::iota_view(std::forward<_Start>(__start))))378-> decltype(ranges::iota_view(std::forward<_Start>(__start))) {379return ranges::iota_view(std::forward<_Start>(__start));380}381382template <class _Start, class _BoundSentinel>383_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Start&& __start, _BoundSentinel&& __bound_sentinel) const noexcept(384noexcept(ranges::iota_view(std::forward<_Start>(__start), std::forward<_BoundSentinel>(__bound_sentinel))))385-> decltype(ranges::iota_view(std::forward<_Start>(__start), std::forward<_BoundSentinel>(__bound_sentinel))) {386return ranges::iota_view(std::forward<_Start>(__start), std::forward<_BoundSentinel>(__bound_sentinel));387}388};389} // namespace __iota390391inline namespace __cpo {392inline constexpr auto iota = __iota::__fn{};393} // namespace __cpo394} // namespace views395} // namespace ranges396397#endif // _LIBCPP_STD_VER >= 20398399_LIBCPP_END_NAMESPACE_STD400401_LIBCPP_POP_MACROS402403#endif // _LIBCPP___RANGES_IOTA_VIEW_H404405406