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___CXX03___ITERATOR_ALIASING_ITERATOR_H |
10 | #define _LIBCPP___CXX03___ITERATOR_ALIASING_ITERATOR_H |
11 | |
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_header |
20 | #endif |
21 | |
22 | // This iterator wrapper is used to type-pun an iterator to return a different type. This is done without UB by not |
23 | // actually punning the type, but instead inspecting the object representation of the base type and copying that into |
24 | // an instance of the alias type. For that reason the alias type has to be trivial. The alias is returned as a prvalue |
25 | // when derferencing the iterator, since it is temporary storage. This wrapper is used to vectorize some algorithms. |
26 | |
27 | _LIBCPP_BEGIN_NAMESPACE_STD |
28 | |
29 | template <class _BaseIter, class _Alias> |
30 | struct __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 _BaseT |
122 | template <class _BaseT, class _Alias> |
123 | using __aliasing_iterator = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator; |
124 | |
125 | _LIBCPP_END_NAMESPACE_STD |
126 | |
127 | #endif // _LIBCPP___CXX03___ITERATOR_ALIASING_ITERATOR_H |
128 |
Warning: This file is not a C or C++ file. It does not have highlighting.