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