/src/immer/immer/detail/util.hpp
Line | Count | Source |
1 | | // |
2 | | // immer: immutable data structures for C++ |
3 | | // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente |
4 | | // |
5 | | // This software is distributed under the Boost Software License, Version 1.0. |
6 | | // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt |
7 | | // |
8 | | |
9 | | #pragma once |
10 | | |
11 | | #include <immer/config.hpp> |
12 | | |
13 | | #include <cstddef> |
14 | | #include <memory> |
15 | | #include <new> |
16 | | #include <type_traits> |
17 | | |
18 | | #include <immer/detail/type_traits.hpp> |
19 | | |
20 | | #if defined(_MSC_VER) |
21 | | #include <intrin.h> // for __lzcnt* |
22 | | #endif |
23 | | |
24 | | namespace immer { |
25 | | namespace detail { |
26 | | |
27 | | template <typename T> |
28 | | const T* as_const(T* x) |
29 | | { |
30 | | return x; |
31 | | } |
32 | | |
33 | | template <typename T> |
34 | | const T& as_const(T& x) |
35 | | { |
36 | | return x; |
37 | | } |
38 | | |
39 | | template <std::size_t Size, std::size_t Align> |
40 | | struct aligned_storage |
41 | | { |
42 | | struct type |
43 | | { |
44 | | alignas(Align) unsigned char data[Size]; |
45 | | }; |
46 | | }; |
47 | | |
48 | | template <std::size_t Size, std::size_t Align> |
49 | | using aligned_storage_t = typename aligned_storage<Size, Align>::type; |
50 | | |
51 | | template <typename T> |
52 | | using aligned_storage_for = |
53 | | typename aligned_storage<sizeof(T), alignof(T)>::type; |
54 | | |
55 | | /*! |
56 | | * CRTP class that allows using the storage immediately following an instance of |
57 | | * the derived class to store objects of type `T` (i.e. "trailing storage"). |
58 | | * |
59 | | * The class is guaranteed to be standard layout if the derived class is also |
60 | | * standard_layout. |
61 | | * |
62 | | * `EmptyStruct` should be set to `true` if the derived class is empty, this |
63 | | * allows the optimization of using the storage of the derived class as trailing |
64 | | * storage. |
65 | | */ |
66 | | template <typename Derived, typename T, bool EmptyStruct = false> |
67 | | struct with_trailing_storage; |
68 | | |
69 | | template <typename Derived, typename T> |
70 | | struct alignas(alignof(T)) with_trailing_storage<Derived, T, true> |
71 | | { |
72 | | using storage_type = T; |
73 | | |
74 | | T* get_storage_ptr() |
75 | 8.95M | { |
76 | 8.95M | check_base(); |
77 | 8.95M | return reinterpret_cast<T*>(this); |
78 | 8.95M | } |
79 | | |
80 | | const T* get_storage_ptr() const |
81 | | { |
82 | | check_base(); |
83 | | return reinterpret_cast<const T*>(this); |
84 | | } |
85 | | |
86 | | static constexpr size_t get_storage_offset() |
87 | 383k | { |
88 | 383k | check_base(); |
89 | 383k | return 0; |
90 | 383k | } immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::leaf_t, int, true>::get_storage_offset() Line | Count | Source | 87 | 383k | { | 88 | 383k | check_base(); | 89 | 383k | return 0; | 90 | 383k | } |
Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 5u>::leaf_t, int, true>::get_storage_offset() Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 6u>::leaf_t, int, true>::get_storage_offset() |
91 | | |
92 | | private: |
93 | | static constexpr void check_base() |
94 | 9.33M | { |
95 | | // is_standard_layout requires that only one class in the hierarchy |
96 | | // contains non-static data members. Since this class contains one |
97 | | // member, the static_assert will only hold when the derived class is |
98 | | // empty. |
99 | 9.33M | static_assert(std::is_standard_layout<Derived>::value, |
100 | 9.33M | "Please remove 'true' if the derived class is non emtpy"); |
101 | 9.33M | } immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::leaf_t, int, true>::check_base() Line | Count | Source | 94 | 9.33M | { | 95 | | // is_standard_layout requires that only one class in the hierarchy | 96 | | // contains non-static data members. Since this class contains one | 97 | | // member, the static_assert will only hold when the derived class is | 98 | | // empty. | 99 | 9.33M | static_assert(std::is_standard_layout<Derived>::value, | 100 | 9.33M | "Please remove 'true' if the derived class is non emtpy"); | 101 | 9.33M | } |
Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 5u>::leaf_t, int, true>::check_base() Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 6u>::leaf_t, int, true>::check_base() |
102 | | |
103 | | // Dummy field to make the base class non-empty. |
104 | | char _; |
105 | | }; |
106 | | |
107 | | template <typename Derived, typename T> |
108 | | struct alignas(alignof(T)) with_trailing_storage<Derived, T, false> |
109 | | { |
110 | | using storage_type = T; |
111 | | |
112 | | T* get_storage_ptr() |
113 | 37.0M | { |
114 | 37.0M | check_base(); |
115 | 37.0M | auto* base = static_cast<Derived*>(this); |
116 | 37.0M | return reinterpret_cast<T*>(base + 1); |
117 | 37.0M | } |
118 | | |
119 | | const T* get_storage_ptr() const |
120 | | { |
121 | | check_base(); |
122 | | auto* base = static_cast<const Derived*>(this); |
123 | | return reinterpret_cast<const T*>(base + 1); |
124 | | } |
125 | | |
126 | | static constexpr size_t get_storage_offset() |
127 | 926k | { |
128 | 926k | check_base(); |
129 | 926k | return sizeof(Derived); |
130 | 926k | } immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::inner_t, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*, false>::get_storage_offset() Line | Count | Source | 127 | 926k | { | 128 | 926k | check_base(); | 129 | 926k | return sizeof(Derived); | 130 | 926k | } |
Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 5u>::inner_t, immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 5u>*, false>::get_storage_offset() Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 6u>::inner_t, immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 6u>*, false>::get_storage_offset() |
131 | | |
132 | | private: |
133 | | static constexpr void check_base() |
134 | 38.0M | { |
135 | 38.0M | static_assert(std::is_standard_layout<Derived>::value && |
136 | 38.0M | !std::is_empty<Derived>::value, |
137 | 38.0M | "Please add 'true' if the derived class is emtpy"); |
138 | 38.0M | } immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::inner_t, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*, false>::check_base() Line | Count | Source | 134 | 38.0M | { | 135 | 38.0M | static_assert(std::is_standard_layout<Derived>::value && | 136 | 38.0M | !std::is_empty<Derived>::value, | 137 | 38.0M | "Please add 'true' if the derived class is emtpy"); | 138 | 38.0M | } |
Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 5u>::inner_t, immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 5u>*, false>::check_base() Unexecuted instantiation: immer::detail::with_trailing_storage<immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 6u>::inner_t, immer::detail::rbts::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true>, 5u, 6u>*, false>::check_base() |
139 | | }; |
140 | | |
141 | | template <typename T> |
142 | | T& auto_const_cast(const T& x) |
143 | 22.4M | { |
144 | 22.4M | return const_cast<T&>(x); |
145 | 22.4M | } |
146 | | template <typename T> |
147 | | T&& auto_const_cast(const T&& x) |
148 | | { |
149 | | return const_cast<T&&>(std::move(x)); |
150 | | } |
151 | | |
152 | | template <class T> |
153 | | inline auto destroy_at(T* p) noexcept |
154 | | -> std::enable_if_t<std::is_trivially_destructible<T>::value> |
155 | | { |
156 | | p->~T(); |
157 | | } |
158 | | |
159 | | template <class T> |
160 | | inline auto destroy_at(T* p) noexcept |
161 | | -> std::enable_if_t<!std::is_trivially_destructible<T>::value> |
162 | | { |
163 | | p->~T(); |
164 | | } |
165 | | |
166 | | template <typename Iter1> |
167 | | constexpr bool can_trivially_detroy = std::is_trivially_destructible< |
168 | | typename std::iterator_traits<Iter1>::value_type>::value; |
169 | | |
170 | | template <class Iter> |
171 | | auto destroy(Iter, Iter last) noexcept |
172 | | -> std::enable_if_t<can_trivially_detroy<Iter>, Iter> |
173 | | { |
174 | | return last; |
175 | | } |
176 | | template <class Iter> |
177 | | auto destroy(Iter first, Iter last) noexcept |
178 | | -> std::enable_if_t<!can_trivially_detroy<Iter>, Iter> |
179 | | { |
180 | | for (; first != last; ++first) |
181 | | detail::destroy_at(std::addressof(*first)); |
182 | | return first; |
183 | | } |
184 | | |
185 | | template <class Iter, class Size> |
186 | | auto destroy_n(Iter first, Size n) noexcept |
187 | | -> std::enable_if_t<can_trivially_detroy<Iter>, Iter> |
188 | 3.97k | { |
189 | 3.97k | return first + n; |
190 | 3.97k | } std::__1::enable_if<can_trivially_detroy<int*>, int*>::type immer::detail::destroy_n<int*, unsigned int>(int*, unsigned int) Line | Count | Source | 188 | 3.42k | { | 189 | 3.42k | return first + n; | 190 | 3.42k | } |
std::__1::enable_if<can_trivially_detroy<int*>, int*>::type immer::detail::destroy_n<int*, unsigned long>(int*, unsigned long) Line | Count | Source | 188 | 551 | { | 189 | 551 | return first + n; | 190 | 551 | } |
|
191 | | template <class Iter, class Size> |
192 | | auto destroy_n(Iter first, Size n) noexcept |
193 | | -> std::enable_if_t<!can_trivially_detroy<Iter>, Iter> |
194 | | { |
195 | | for (; n > 0; (void) ++first, --n) |
196 | | detail::destroy_at(std::addressof(*first)); |
197 | | return first; |
198 | | } |
199 | | |
200 | | template <typename Iter1, typename Iter2> |
201 | | constexpr bool can_trivially_copy = |
202 | | std::is_same<typename std::iterator_traits<Iter1>::value_type, |
203 | | typename std::iterator_traits<Iter2>::value_type>::value && |
204 | | std::is_trivially_copyable< |
205 | | typename std::iterator_traits<Iter1>::value_type>::value; |
206 | | |
207 | | template <typename Iter1, typename Iter2> |
208 | | auto uninitialized_move(Iter1 first, Iter1 last, Iter2 out) noexcept |
209 | | -> std::enable_if_t<can_trivially_copy<Iter1, Iter2>, Iter2> |
210 | 2.04k | { |
211 | 2.04k | return std::copy(first, last, out); |
212 | 2.04k | } |
213 | | template <typename Iter1, typename Iter2> |
214 | | auto uninitialized_move(Iter1 first, Iter1 last, Iter2 out) |
215 | | -> std::enable_if_t<!can_trivially_copy<Iter1, Iter2>, Iter2> |
216 | | |
217 | | { |
218 | | using value_t = typename std::iterator_traits<Iter2>::value_type; |
219 | | auto current = out; |
220 | | IMMER_TRY { |
221 | | for (; first != last; ++first, (void) ++current) { |
222 | | ::new (const_cast<void*>(static_cast<const volatile void*>( |
223 | | std::addressof(*current)))) value_t(std::move(*first)); |
224 | | } |
225 | | return current; |
226 | | } |
227 | | IMMER_CATCH (...) { |
228 | | detail::destroy(out, current); |
229 | | IMMER_RETHROW; |
230 | | } |
231 | | } |
232 | | |
233 | | template <typename SourceIter, typename Sent, typename SinkIter> |
234 | | auto uninitialized_copy(SourceIter first, Sent last, SinkIter out) noexcept |
235 | | -> std::enable_if_t<can_trivially_copy<SourceIter, SinkIter>, SinkIter> |
236 | 2.96M | { |
237 | 2.96M | return std::copy(first, last, out); |
238 | 2.96M | } |
239 | | template <typename SourceIter, typename Sent, typename SinkIter> |
240 | | auto uninitialized_copy(SourceIter first, Sent last, SinkIter out) |
241 | | -> std::enable_if_t<!can_trivially_copy<SourceIter, SinkIter>, SinkIter> |
242 | | { |
243 | | using value_t = typename std::iterator_traits<SinkIter>::value_type; |
244 | | auto current = out; |
245 | | IMMER_TRY { |
246 | | for (; first != last; ++first, (void) ++current) { |
247 | | ::new (const_cast<void*>(static_cast<const volatile void*>( |
248 | | std::addressof(*current)))) value_t(*first); |
249 | | } |
250 | | return current; |
251 | | } |
252 | | IMMER_CATCH (...) { |
253 | | detail::destroy(out, current); |
254 | | IMMER_RETHROW; |
255 | | } |
256 | | } |
257 | | |
258 | | template <typename Heap, typename T, typename... Args> |
259 | | T* make(Args&&... args) |
260 | | { |
261 | | auto ptr = Heap::allocate(sizeof(T)); |
262 | | IMMER_TRY { |
263 | | return new (ptr) T(std::forward<Args>(args)...); |
264 | | } |
265 | | IMMER_CATCH (...) { |
266 | | Heap::deallocate(sizeof(T), ptr); |
267 | | IMMER_RETHROW; |
268 | | } |
269 | | } |
270 | | |
271 | | struct not_supported_t |
272 | | {}; |
273 | | struct empty_t |
274 | | {}; |
275 | | |
276 | | template <typename T> |
277 | | struct exact_t |
278 | | { |
279 | | T value; |
280 | | exact_t(T v) |
281 | | : value{v} {}; |
282 | | }; |
283 | | |
284 | | template <typename T> |
285 | | inline constexpr auto clz_(T) -> not_supported_t |
286 | | { |
287 | | IMMER_UNREACHABLE; |
288 | | return {}; |
289 | | } |
290 | | #if defined(_MSC_VER) |
291 | | // inline auto clz_(unsigned short x) { return __lzcnt16(x); } |
292 | | // inline auto clz_(unsigned int x) { return __lzcnt(x); } |
293 | | // inline auto clz_(unsigned __int64 x) { return __lzcnt64(x); } |
294 | | #else |
295 | 0 | inline constexpr auto clz_(unsigned int x) { return __builtin_clz(x); } |
296 | 0 | inline constexpr auto clz_(unsigned long x) { return __builtin_clzl(x); } |
297 | 0 | inline constexpr auto clz_(unsigned long long x) { return __builtin_clzll(x); } |
298 | | #endif |
299 | | |
300 | | template <typename T> |
301 | | inline constexpr T log2_aux(T x, T r = 0) |
302 | | { |
303 | | return x <= 1 ? r : log2_aux(x >> 1, r + 1); |
304 | | } |
305 | | |
306 | | template <typename T> |
307 | | inline constexpr auto log2(T x) -> std:: |
308 | | enable_if_t<!std::is_same<decltype(clz_(x)), not_supported_t>::value, T> |
309 | 0 | { |
310 | 0 | return x == 0 ? 0 : sizeof(std::size_t) * 8 - 1 - clz_(x); |
311 | 0 | } |
312 | | |
313 | | template <typename T> |
314 | | inline constexpr auto log2(T x) |
315 | | -> std::enable_if_t<std::is_same<decltype(clz_(x)), not_supported_t>::value, |
316 | | T> |
317 | | { |
318 | | return log2_aux(x); |
319 | | } |
320 | | |
321 | | template <typename T> |
322 | | constexpr T ipow(T num, unsigned int pow) |
323 | 64.8M | { |
324 | 64.8M | return pow == 0 ? 1 : num * ipow(num, pow - 1); |
325 | 64.8M | } |
326 | | |
327 | | template <bool b, typename F> |
328 | | auto static_if(F&& f) -> std::enable_if_t<b> |
329 | 875k | { |
330 | 875k | std::forward<F>(f)(empty_t{}); |
331 | 875k | } Unexecuted instantiation: std::__1::enable_if<true, void>::type immer::detail::static_if<true, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::delete_inner_r(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*, unsigned int)::{lambda(auto:1)#1}>(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::delete_inner_r(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*, unsigned int)::{lambda(auto:1)#1}&&)std::__1::enable_if<true, void>::type immer::detail::static_if<true, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_r_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit)::{lambda(auto:1)#1}>(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_r_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit)::{lambda(auto:1)#1}&&)Line | Count | Source | 329 | 875k | { | 330 | 875k | std::forward<F>(f)(empty_t{}); | 331 | 875k | } |
Unexecuted instantiation: std::__1::enable_if<true, void>::type immer::detail::static_if<true, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::delete_inner_r_e(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*)::{lambda(auto:1)#1}>(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::delete_inner_r_e(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*)::{lambda(auto:1)#1}&&) |
332 | | template <bool b, typename F> |
333 | | auto static_if(F&& f) -> std::enable_if_t<!b> |
334 | | { |
335 | | } |
336 | | |
337 | | template <bool b, typename R = void, typename F1, typename F2> |
338 | | auto static_if(F1&& f1, F2&& f2) -> std::enable_if_t<b, R> |
339 | | { |
340 | | return std::forward<F1>(f1)(empty_t{}); |
341 | | } |
342 | | template <bool b, typename R = void, typename F1, typename F2> |
343 | | auto static_if(F1&& f1, F2&& f2) -> std::enable_if_t<!b, R> |
344 | 1.49M | { |
345 | 1.49M | return std::forward<F2>(f2)(empty_t{}); |
346 | 1.49M | } std::__1::enable_if<!(false), immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*>::type immer::detail::static_if<false, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_n(unsigned int, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#1}, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_n(unsigned int, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#2}>(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_n(unsigned int, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#1}&&, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_n(unsigned int, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#2}&&)Line | Count | Source | 344 | 30.1k | { | 345 | 30.1k | return std::forward<F2>(f2)(empty_t{}); | 346 | 30.1k | } |
std::__1::enable_if<!(false), immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*>::type immer::detail::static_if<false, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_n(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned int)::{lambda(auto:1)#1}, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_n(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned int)::{lambda(auto:1)#2}>(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_n(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned int)::{lambda(auto:1)#1}&&, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_n(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned int)::{lambda(auto:1)#2}&&)Line | Count | Source | 344 | 894k | { | 345 | 894k | return std::forward<F2>(f2)(empty_t{}); | 346 | 894k | } |
std::__1::enable_if<!(false), immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*>::type immer::detail::static_if<false, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>*, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#1}, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#2}>(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#1}&&, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::make_inner_sr_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*)::{lambda(auto:1)#2}&&)Line | Count | Source | 344 | 18.9k | { | 345 | 18.9k | return std::forward<F2>(f2)(empty_t{}); | 346 | 18.9k | } |
std::__1::enable_if<!(false), immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*>::type immer::detail::static_if<false, immer::detail::csl::member_two<immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::relaxed_data_t, immer::detail::csl::inherit<immer::no_refcount_policy, immer::detail::csl::member<immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::ownee, void>::type>::type>::type*, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit)::{lambda(auto:1)#1}, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit)::{lambda(auto:1)#2}>(immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit)::{lambda(auto:1)#1}&&, immer::detail::rbts::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>::ensure_mutable_relaxed_e(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit)::{lambda(auto:1)#2}&&)Line | Count | Source | 344 | 555k | { | 345 | 555k | return std::forward<F2>(f2)(empty_t{}); | 346 | 555k | } |
|
347 | | |
348 | | template <typename T, T value> |
349 | | struct constantly |
350 | | { |
351 | | template <typename... Args> |
352 | | T operator()(Args&&...) const |
353 | | { |
354 | | return value; |
355 | | } |
356 | | }; |
357 | | |
358 | | /*! |
359 | | * An alias to `std::distance` |
360 | | */ |
361 | | template <typename Iterator, |
362 | | typename Sentinel, |
363 | | std::enable_if_t<detail::std_distance_supports_v<Iterator, Sentinel>, |
364 | | bool> = true> |
365 | | typename std::iterator_traits<Iterator>::difference_type |
366 | | distance(Iterator first, Sentinel last) |
367 | | { |
368 | | return std::distance(first, last); |
369 | | } |
370 | | |
371 | | /*! |
372 | | * Equivalent of the `std::distance` applied to the sentinel-delimited |
373 | | * forward range @f$ [first, last) @f$ |
374 | | */ |
375 | | template <typename Iterator, |
376 | | typename Sentinel, |
377 | | std::enable_if_t< |
378 | | (!detail::std_distance_supports_v<Iterator, Sentinel>) &&detail:: |
379 | | is_forward_iterator_v<Iterator> && |
380 | | detail::compatible_sentinel_v<Iterator, Sentinel> && |
381 | | (!detail::is_subtractable_v<Sentinel, Iterator>), |
382 | | bool> = true> |
383 | | typename std::iterator_traits<Iterator>::difference_type |
384 | | distance(Iterator first, Sentinel last) |
385 | | { |
386 | | std::size_t result = 0; |
387 | | while (first != last) { |
388 | | ++first; |
389 | | ++result; |
390 | | } |
391 | | return result; |
392 | | } |
393 | | |
394 | | /*! |
395 | | * Equivalent of the `std::distance` applied to the sentinel-delimited |
396 | | * random access range @f$ [first, last) @f$ |
397 | | */ |
398 | | template <typename Iterator, |
399 | | typename Sentinel, |
400 | | std::enable_if_t< |
401 | | (!detail::std_distance_supports_v<Iterator, Sentinel>) &&detail:: |
402 | | is_forward_iterator_v<Iterator> && |
403 | | detail::compatible_sentinel_v<Iterator, Sentinel> && |
404 | | detail::is_subtractable_v<Sentinel, Iterator>, |
405 | | bool> = true> |
406 | | typename std::iterator_traits<Iterator>::difference_type |
407 | | distance(Iterator first, Sentinel last) |
408 | | { |
409 | | return last - first; |
410 | | } |
411 | | |
412 | | } // namespace detail |
413 | | } // namespace immer |