codekingpro/portable-devtools
114k
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.8//9//===----------------------------------------------------------------------===//10 11#ifndef _LIBCUDACXX___ITERATOR_BOUNDED_ITER_H12#define _LIBCUDACXX___ITERATOR_BOUNDED_ITER_H13 14#ifndef __cuda_std__15#include <__config>16#endif // __cuda_std__17 18#include "../__assert"19#include "../__iterator/iterator_traits.h"20#include "../__memory/pointer_traits.h"21#include "../__type_traits/enable_if.h"22#include "../__type_traits/is_convertible.h"23#include "../__utility/move.h"24 25#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)26# pragma GCC system_header27#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)28# pragma clang system_header29#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)30# pragma system_header31#endif // no system header32 33_LIBCUDACXX_BEGIN_NAMESPACE_STD34 35// Iterator wrapper that carries the valid range it is allowed to access.36//37// This is a simple iterator wrapper for contiguous iterators that points38// within a [begin, end) range and carries these bounds with it. The iterator39// ensures that it is pointing within that [begin, end) range when it is40// dereferenced.41//42// Arithmetic operations are allowed and the bounds of the resulting iterator43// are not checked. Hence, it is possible to create an iterator pointing outside44// its range, but it is not possible to dereference it.45template <class _Iterator, class = __enable_if_t< __is_cpp17_contiguous_iterator<_Iterator>::value > >46struct __bounded_iter {47 using value_type = typename iterator_traits<_Iterator>::value_type;48 using difference_type = typename iterator_traits<_Iterator>::difference_type;49 using pointer = typename iterator_traits<_Iterator>::pointer;50 using reference = typename iterator_traits<_Iterator>::reference;51 using iterator_category = typename iterator_traits<_Iterator>::iterator_category;52#if _LIBCUDACXX_STD_VER > 1453 using iterator_concept = contiguous_iterator_tag;54#endif55 56 // Create a singular iterator.57 //58 // Such an iterator does not point to any object and is conceptually out of bounds, so it is59 // not dereferenceable. Observing operations like comparison and assignment are valid.60 __bounded_iter() = default;61 62 __bounded_iter(__bounded_iter const&) = default;63 __bounded_iter(__bounded_iter&&) = default;64 65 template <class _OtherIterator, class = __enable_if_t<is_convertible<_OtherIterator, _Iterator>::value > >66 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY67 constexpr __bounded_iter(__bounded_iter<_OtherIterator> const& __other) noexcept68 : __current_(__other.__current_),69 __begin_(__other.__begin_),70 __end_(__other.__end_) {}71 72 // Assign a bounded iterator to another one, rebinding the bounds of the iterator as well.73 __bounded_iter& operator=(__bounded_iter const&) = default;74 __bounded_iter& operator=(__bounded_iter&&) = default;75 76private:77 // Create an iterator wrapping the given iterator, and whose bounds are described78 // by the provided [begin, end) range.79 //80 // This constructor does not check whether the resulting iterator is within its bounds.81 // However, it does check that the provided [begin, end) range is a valid range (that82 // is, begin <= end).83 //84 // Since it is non-standard for iterators to have this constructor, __bounded_iter must85 // be created via `_CUDA_VSTD::__make_bounded_iter`.86 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY87 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 explicit __bounded_iter(88 _Iterator __current, _Iterator __begin, _Iterator __end)89 : __current_(__current), __begin_(__begin), __end_(__end) {90 _LIBCUDACXX_ASSERT(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range");91 }92 93 template <class _It>94 friend _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY95 constexpr __bounded_iter<_It> __make_bounded_iter(_It, _It, _It);96 97public:98 // Dereference and indexing operations.99 //100 // These operations check that the iterator is dereferenceable, that is within [begin, end).101 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY102 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 reference operator*() const noexcept {103 _LIBCUDACXX_ASSERT(104 __in_bounds(__current_), "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator");105 return *__current_;106 }107 108 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY109 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 pointer operator->() const noexcept {110 _LIBCUDACXX_ASSERT(111 __in_bounds(__current_), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator");112 return _CUDA_VSTD::__to_address(__current_);113 }114 115 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY116 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 reference operator[](difference_type __n) const noexcept {117 _LIBCUDACXX_ASSERT(118 __in_bounds(__current_ + __n), "__bounded_iter::operator[]: Attempt to index an iterator out-of-range");119 return __current_[__n];120 }121 122 // Arithmetic operations.123 //124 // These operations do not check that the resulting iterator is within the bounds, since that125 // would make it impossible to create a past-the-end iterator.126 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY127 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 __bounded_iter& operator++() noexcept {128 ++__current_;129 return *this;130 }131 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY132 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 __bounded_iter operator++(int) noexcept {133 __bounded_iter __tmp(*this);134 ++*this;135 return __tmp;136 }137 138 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY139 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 __bounded_iter& operator--() noexcept {140 --__current_;141 return *this;142 }143 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY144 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 __bounded_iter operator--(int) noexcept {145 __bounded_iter __tmp(*this);146 --*this;147 return __tmp;148 }149 150 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY151 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 __bounded_iter& operator+=(difference_type __n) noexcept {152 __current_ += __n;153 return *this;154 }155 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY156 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 friend __bounded_iter157 operator+(__bounded_iter const& __self, difference_type __n) noexcept {158 __bounded_iter __tmp(__self);159 __tmp += __n;160 return __tmp;161 }162 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY163 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 friend __bounded_iter164 operator+(difference_type __n, __bounded_iter const& __self) noexcept {165 __bounded_iter __tmp(__self);166 __tmp += __n;167 return __tmp;168 }169 170 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY171 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 __bounded_iter& operator-=(difference_type __n) noexcept {172 __current_ -= __n;173 return *this;174 }175 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY176 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 friend __bounded_iter177 operator-(__bounded_iter const& __self, difference_type __n) noexcept {178 __bounded_iter __tmp(__self);179 __tmp -= __n;180 return __tmp;181 }182 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY183 _LIBCUDACXX_CONSTEXPR_AFTER_CXX11 friend difference_type184 operator-(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {185 return __x.__current_ - __y.__current_;186 }187 188 // Comparison operations.189 //190 // These operations do not check whether the iterators are within their bounds.191 // The valid range for each iterator is also not considered as part of the comparison,192 // i.e. two iterators pointing to the same location will be considered equal even193 // if they have different validity ranges.194 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY195 constexpr friend bool196 operator==(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {197 return __x.__current_ == __y.__current_;198 }199 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY200 constexpr friend bool201 operator!=(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {202 return __x.__current_ != __y.__current_;203 }204 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY205 constexpr friend bool206 operator<(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {207 return __x.__current_ < __y.__current_;208 }209 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY210 constexpr friend bool211 operator>(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {212 return __x.__current_ > __y.__current_;213 }214 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY215 constexpr friend bool216 operator<=(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {217 return __x.__current_ <= __y.__current_;218 }219 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY220 constexpr friend bool221 operator>=(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {222 return __x.__current_ >= __y.__current_;223 }224 225private:226 // Return whether the given iterator is in the bounds of this __bounded_iter.227 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY228 constexpr bool __in_bounds(_Iterator const& __iter) const {229 return __iter >= __begin_ && __iter < __end_;230 }231 232 template <class>233 friend struct pointer_traits;234 _Iterator __current_; // current iterator235 _Iterator __begin_, __end_; // valid range represented as [begin, end)236};237 238template <class _It>239_LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY240constexpr __bounded_iter<_It> __make_bounded_iter(_It __it, _It __begin, _It __end) {241 return __bounded_iter<_It>(_CUDA_VSTD::move(__it), _CUDA_VSTD::move(__begin), _CUDA_VSTD::move(__end));242}243 244#if _LIBCUDACXX_STD_VER <= 17245template <class _Iterator>246struct __is_cpp17_contiguous_iterator<__bounded_iter<_Iterator> > : true_type {};247#endif248 249template <class _Iterator>250struct pointer_traits<__bounded_iter<_Iterator> > {251 using pointer = __bounded_iter<_Iterator>;252 using element_type = typename pointer_traits<_Iterator>::element_type;253 using difference_type = typename pointer_traits<_Iterator>::difference_type;254 255 _LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY256 constexpr static element_type* to_address(pointer __it) noexcept {257 return _CUDA_VSTD::__to_address(__it.__current_);258 }259};260 261_LIBCUDACXX_END_NAMESPACE_STD262 263#endif // _LIBCUDACXX___ITERATOR_BOUNDED_ITER_H264 