128 lines · 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//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___CXX03___ITERATOR_ALIASING_ITERATOR_H10#define _LIBCPP___CXX03___ITERATOR_ALIASING_ITERATOR_H11 12#include <__cxx03/__config>13#include <__cxx03/__iterator/iterator_traits.h>14#include <__cxx03/__memory/pointer_traits.h>15#include <__cxx03/__type_traits/is_trivial.h>16#include <__cxx03/cstddef>17 18#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)19# pragma GCC system_header20#endif21 22// This iterator wrapper is used to type-pun an iterator to return a different type. This is done without UB by not23// actually punning the type, but instead inspecting the object representation of the base type and copying that into24// an instance of the alias type. For that reason the alias type has to be trivial. The alias is returned as a prvalue25// when derferencing the iterator, since it is temporary storage. This wrapper is used to vectorize some algorithms.26 27_LIBCPP_BEGIN_NAMESPACE_STD28 29template <class _BaseIter, class _Alias>30struct __aliasing_iterator_wrapper {31 class __iterator {32 _BaseIter __base_ = nullptr;33 34 using __iter_traits = iterator_traits<_BaseIter>;35 using __base_value_type = typename __iter_traits::value_type;36 37 static_assert(__has_random_access_iterator_category<_BaseIter>::value,38 "The base iterator has to be a random access iterator!");39 40 public:41 using iterator_category = random_access_iterator_tag;42 using value_type = _Alias;43 using difference_type = ptrdiff_t;44 using reference = value_type&;45 using pointer = value_type*;46 47 static_assert(is_trivial<value_type>::value);48 static_assert(sizeof(__base_value_type) == sizeof(value_type));49 50 _LIBCPP_HIDE_FROM_ABI __iterator() = default;51 _LIBCPP_HIDE_FROM_ABI __iterator(_BaseIter __base) _NOEXCEPT : __base_(__base) {}52 53 _LIBCPP_HIDE_FROM_ABI __iterator& operator++() _NOEXCEPT {54 ++__base_;55 return *this;56 }57 58 _LIBCPP_HIDE_FROM_ABI __iterator operator++(int) _NOEXCEPT {59 __iterator __tmp(*this);60 ++__base_;61 return __tmp;62 }63 64 _LIBCPP_HIDE_FROM_ABI __iterator& operator--() _NOEXCEPT {65 --__base_;66 return *this;67 }68 69 _LIBCPP_HIDE_FROM_ABI __iterator operator--(int) _NOEXCEPT {70 __iterator __tmp(*this);71 --__base_;72 return __tmp;73 }74 75 _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(__iterator __iter, difference_type __n) _NOEXCEPT {76 return __iterator(__iter.__base_ + __n);77 }78 79 _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(difference_type __n, __iterator __iter) _NOEXCEPT {80 return __iterator(__n + __iter.__base_);81 }82 83 _LIBCPP_HIDE_FROM_ABI __iterator& operator+=(difference_type __n) _NOEXCEPT {84 __base_ += __n;85 return *this;86 }87 88 _LIBCPP_HIDE_FROM_ABI friend __iterator operator-(__iterator __iter, difference_type __n) _NOEXCEPT {89 return __iterator(__iter.__base_ - __n);90 }91 92 _LIBCPP_HIDE_FROM_ABI friend difference_type operator-(__iterator __lhs, __iterator __rhs) _NOEXCEPT {93 return __lhs.__base_ - __rhs.__base_;94 }95 96 _LIBCPP_HIDE_FROM_ABI __iterator& operator-=(difference_type __n) _NOEXCEPT {97 __base_ -= __n;98 return *this;99 }100 101 _LIBCPP_HIDE_FROM_ABI _BaseIter __base() const _NOEXCEPT { return __base_; }102 103 _LIBCPP_HIDE_FROM_ABI _Alias operator*() const _NOEXCEPT {104 _Alias __val;105 __builtin_memcpy(&__val, std::__to_address(__base_), sizeof(value_type));106 return __val;107 }108 109 _LIBCPP_HIDE_FROM_ABI value_type operator[](difference_type __n) const _NOEXCEPT { return *(*this + __n); }110 111 _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __lhs, const __iterator& __rhs) _NOEXCEPT {112 return __lhs.__base_ == __rhs.__base_;113 }114 115 _LIBCPP_HIDE_FROM_ABI friend bool operator!=(const __iterator& __lhs, const __iterator& __rhs) _NOEXCEPT {116 return __lhs.__base_ != __rhs.__base_;117 }118 };119};120 121// This is required to avoid ADL instantiations on _BaseT122template <class _BaseT, class _Alias>123using __aliasing_iterator = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator;124 125_LIBCPP_END_NAMESPACE_STD126 127#endif // _LIBCPP___CXX03___ITERATOR_ALIASING_ITERATOR_H128