1*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #ifndef _LIBCPP___ITERATOR_ALIASING_ITERATOR_H 10*0fca6ea1SDimitry Andric #define _LIBCPP___ITERATOR_ALIASING_ITERATOR_H 11*0fca6ea1SDimitry Andric 12*0fca6ea1SDimitry Andric #include <__config> 13*0fca6ea1SDimitry Andric #include <__iterator/iterator_traits.h> 14*0fca6ea1SDimitry Andric #include <__memory/pointer_traits.h> 15*0fca6ea1SDimitry Andric #include <__type_traits/is_trivial.h> 16*0fca6ea1SDimitry Andric #include <cstddef> 17*0fca6ea1SDimitry Andric 18*0fca6ea1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19*0fca6ea1SDimitry Andric # pragma GCC system_header 20*0fca6ea1SDimitry Andric #endif 21*0fca6ea1SDimitry Andric 22*0fca6ea1SDimitry Andric // This iterator wrapper is used to type-pun an iterator to return a different type. This is done without UB by not 23*0fca6ea1SDimitry Andric // actually punning the type, but instead inspecting the object representation of the base type and copying that into 24*0fca6ea1SDimitry Andric // an instance of the alias type. For that reason the alias type has to be trivial. The alias is returned as a prvalue 25*0fca6ea1SDimitry Andric // when derferencing the iterator, since it is temporary storage. This wrapper is used to vectorize some algorithms. 26*0fca6ea1SDimitry Andric 27*0fca6ea1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 28*0fca6ea1SDimitry Andric 29*0fca6ea1SDimitry Andric template <class _BaseIter, class _Alias> 30*0fca6ea1SDimitry Andric struct __aliasing_iterator_wrapper { 31*0fca6ea1SDimitry Andric class __iterator { 32*0fca6ea1SDimitry Andric _BaseIter __base_ = nullptr; 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric using __iter_traits = iterator_traits<_BaseIter>; 35*0fca6ea1SDimitry Andric using __base_value_type = typename __iter_traits::value_type; 36*0fca6ea1SDimitry Andric 37*0fca6ea1SDimitry Andric static_assert(__has_random_access_iterator_category<_BaseIter>::value, 38*0fca6ea1SDimitry Andric "The base iterator has to be a random access iterator!"); 39*0fca6ea1SDimitry Andric 40*0fca6ea1SDimitry Andric public: 41*0fca6ea1SDimitry Andric using iterator_category = random_access_iterator_tag; 42*0fca6ea1SDimitry Andric using value_type = _Alias; 43*0fca6ea1SDimitry Andric using difference_type = ptrdiff_t; 44*0fca6ea1SDimitry Andric using reference = value_type&; 45*0fca6ea1SDimitry Andric using pointer = value_type*; 46*0fca6ea1SDimitry Andric 47*0fca6ea1SDimitry Andric static_assert(is_trivial<value_type>::value); 48*0fca6ea1SDimitry Andric static_assert(sizeof(__base_value_type) == sizeof(value_type)); 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator() = default; 51*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator(_BaseIter __base) _NOEXCEPT : __base_(__base) {} 52*0fca6ea1SDimitry Andric 53*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator& operator++() _NOEXCEPT { 54*0fca6ea1SDimitry Andric ++__base_; 55*0fca6ea1SDimitry Andric return *this; 56*0fca6ea1SDimitry Andric } 57*0fca6ea1SDimitry Andric 58*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator operator++(int) _NOEXCEPT { 59*0fca6ea1SDimitry Andric __iterator __tmp(*this); 60*0fca6ea1SDimitry Andric ++__base_; 61*0fca6ea1SDimitry Andric return __tmp; 62*0fca6ea1SDimitry Andric } 63*0fca6ea1SDimitry Andric 64*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator& operator--() _NOEXCEPT { 65*0fca6ea1SDimitry Andric --__base_; 66*0fca6ea1SDimitry Andric return *this; 67*0fca6ea1SDimitry Andric } 68*0fca6ea1SDimitry Andric 69*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator operator--(int) _NOEXCEPT { 70*0fca6ea1SDimitry Andric __iterator __tmp(*this); 71*0fca6ea1SDimitry Andric --__base_; 72*0fca6ea1SDimitry Andric return __tmp; 73*0fca6ea1SDimitry Andric } 74*0fca6ea1SDimitry Andric 75*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(__iterator __iter, difference_type __n) _NOEXCEPT { 76*0fca6ea1SDimitry Andric return __iterator(__iter.__base_ + __n); 77*0fca6ea1SDimitry Andric } 78*0fca6ea1SDimitry Andric 79*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(difference_type __n, __iterator __iter) _NOEXCEPT { 80*0fca6ea1SDimitry Andric return __iterator(__n + __iter.__base_); 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator& operator+=(difference_type __n) _NOEXCEPT { 84*0fca6ea1SDimitry Andric __base_ += __n; 85*0fca6ea1SDimitry Andric return *this; 86*0fca6ea1SDimitry Andric } 87*0fca6ea1SDimitry Andric 88*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend __iterator operator-(__iterator __iter, difference_type __n) _NOEXCEPT { 89*0fca6ea1SDimitry Andric return __iterator(__iter.__base_ - __n); 90*0fca6ea1SDimitry Andric } 91*0fca6ea1SDimitry Andric 92*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend difference_type operator-(__iterator __lhs, __iterator __rhs) _NOEXCEPT { 93*0fca6ea1SDimitry Andric return __lhs.__base_ - __rhs.__base_; 94*0fca6ea1SDimitry Andric } 95*0fca6ea1SDimitry Andric 96*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator& operator-=(difference_type __n) _NOEXCEPT { 97*0fca6ea1SDimitry Andric __base_ -= __n; 98*0fca6ea1SDimitry Andric return *this; 99*0fca6ea1SDimitry Andric } 100*0fca6ea1SDimitry Andric 101*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _BaseIter __base() const _NOEXCEPT { return __base_; } 102*0fca6ea1SDimitry Andric 103*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _Alias operator*() const _NOEXCEPT { 104*0fca6ea1SDimitry Andric _Alias __val; 105*0fca6ea1SDimitry Andric __builtin_memcpy(&__val, std::__to_address(__base_), sizeof(value_type)); 106*0fca6ea1SDimitry Andric return __val; 107*0fca6ea1SDimitry Andric } 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI value_type operator[](difference_type __n) const _NOEXCEPT { return *(*this + __n); } 110*0fca6ea1SDimitry Andric 111*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __lhs, const __iterator& __rhs) _NOEXCEPT { 112*0fca6ea1SDimitry Andric return __lhs.__base_ == __rhs.__base_; 113*0fca6ea1SDimitry Andric } 114*0fca6ea1SDimitry Andric 115*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend bool operator!=(const __iterator& __lhs, const __iterator& __rhs) _NOEXCEPT { 116*0fca6ea1SDimitry Andric return __lhs.__base_ != __rhs.__base_; 117*0fca6ea1SDimitry Andric } 118*0fca6ea1SDimitry Andric }; 119*0fca6ea1SDimitry Andric }; 120*0fca6ea1SDimitry Andric 121*0fca6ea1SDimitry Andric // This is required to avoid ADL instantiations on _BaseT 122*0fca6ea1SDimitry Andric template <class _BaseT, class _Alias> 123*0fca6ea1SDimitry Andric using __aliasing_iterator = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator; 124*0fca6ea1SDimitry Andric 125*0fca6ea1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 126*0fca6ea1SDimitry Andric 127*0fca6ea1SDimitry Andric #endif // _LIBCPP___ITERATOR_ALIASING_ITERATOR_H 128