Coverage Report

Created: 2026-02-26 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
121k
{
36
121k
    return x;
37
121k
}
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
9.63M
    {
76
9.63M
        check_base();
77
9.63M
        return reinterpret_cast<T*>(this);
78
9.63M
    }
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
689k
    {
88
689k
        check_base();
89
689k
        return 0;
90
689k
    }
91
92
private:
93
    static constexpr void check_base()
94
10.3M
    {
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
10.3M
        static_assert(std::is_standard_layout<Derived>::value,
100
10.3M
                      "Please remove 'true' if the derived class is non emtpy");
101
10.3M
    }
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
48.8M
    {
114
48.8M
        check_base();
115
48.8M
        auto* base = static_cast<Derived*>(this);
116
48.8M
        return reinterpret_cast<T*>(base + 1);
117
48.8M
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::collision_t, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, false>::get_storage_ptr()
Line
Count
Source
113
194k
    {
114
194k
        check_base();
115
194k
        auto* base = static_cast<Derived*>(this);
116
194k
        return reinterpret_cast<T*>(base + 1);
117
194k
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::inner_t, immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>*, false>::get_storage_ptr()
Line
Count
Source
113
48.6M
    {
114
48.6M
        check_base();
115
48.6M
        auto* base = static_cast<Derived*>(this);
116
48.6M
        return reinterpret_cast<T*>(base + 1);
117
48.6M
    }
118
119
    const T* get_storage_ptr() const
120
1.33M
    {
121
1.33M
        check_base();
122
1.33M
        auto* base = static_cast<const Derived*>(this);
123
1.33M
        return reinterpret_cast<const T*>(base + 1);
124
1.33M
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::inner_t, immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>*, false>::get_storage_ptr() const
Line
Count
Source
120
1.30M
    {
121
1.30M
        check_base();
122
1.30M
        auto* base = static_cast<const Derived*>(this);
123
1.30M
        return reinterpret_cast<const T*>(base + 1);
124
1.30M
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::collision_t, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, false>::get_storage_ptr() const
Line
Count
Source
120
28.3k
    {
121
28.3k
        check_base();
122
28.3k
        auto* base = static_cast<const Derived*>(this);
123
28.3k
        return reinterpret_cast<const T*>(base + 1);
124
28.3k
    }
125
126
    static constexpr size_t get_storage_offset()
127
24.0M
    {
128
24.0M
        check_base();
129
24.0M
        return sizeof(Derived);
130
24.0M
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::inner_t, immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>*, false>::get_storage_offset()
Line
Count
Source
127
24.0M
    {
128
24.0M
        check_base();
129
24.0M
        return sizeof(Derived);
130
24.0M
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::collision_t, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, false>::get_storage_offset()
Line
Count
Source
127
42.8k
    {
128
42.8k
        check_base();
129
42.8k
        return sizeof(Derived);
130
42.8k
    }
131
132
private:
133
    static constexpr void check_base()
134
74.2M
    {
135
74.2M
        static_assert(std::is_standard_layout<Derived>::value &&
136
74.2M
                          !std::is_empty<Derived>::value,
137
74.2M
                      "Please add 'true' if the derived class is emtpy");
138
74.2M
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::inner_t, immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>*, false>::check_base()
Line
Count
Source
134
73.9M
    {
135
73.9M
        static_assert(std::is_standard_layout<Derived>::value &&
136
73.9M
                          !std::is_empty<Derived>::value,
137
73.9M
                      "Please add 'true' if the derived class is emtpy");
138
73.9M
    }
immer::detail::with_trailing_storage<immer::detail::hamts::node<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::hash_key, immer::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >, colliding_hash_t, std::__1::equal_to<void>, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::equal_key, immer::memory_policy<immer::heap_policy<immer::cpp_heap>, immer::unsafe_refcount_policy, immer::no_lock_policy, immer::no_transience_policy, false, true>, 3u>::collision_t, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >, false>::check_base()
Line
Count
Source
134
265k
    {
135
265k
        static_assert(std::is_standard_layout<Derived>::value &&
136
265k
                          !std::is_empty<Derived>::value,
137
265k
                      "Please add 'true' if the derived class is emtpy");
138
265k
    }
139
};
140
141
template <typename T>
142
T& auto_const_cast(const T& x)
143
15.3M
{
144
15.3M
    return const_cast<T&>(x);
145
15.3M
}
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
924k
{
163
924k
    p->~T();
164
924k
}
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
0
{
180
0
    for (; first != last; ++first)
181
0
        detail::destroy_at(std::addressof(*first));
182
0
    return first;
183
0
}
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
{
189
    return first + n;
190
}
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
366k
{
195
1.28M
    for (; n > 0; (void) ++first, --n)
196
922k
        detail::destroy_at(std::addressof(*first));
197
366k
    return first;
198
366k
}
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
{
211
    return std::copy(first, last, out);
212
}
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
21.6k
{
218
21.6k
    using value_t = typename std::iterator_traits<Iter2>::value_type;
219
21.6k
    auto current  = out;
220
21.6k
    IMMER_TRY {
221
49.3k
        for (; first != last; ++first, (void) ++current) {
222
27.7k
            ::new (const_cast<void*>(static_cast<const volatile void*>(
223
27.7k
                std::addressof(*current)))) value_t(std::move(*first));
224
27.7k
        }
225
21.6k
        return current;
226
21.6k
    }
227
21.6k
    IMMER_CATCH (...) {
228
0
        detail::destroy(out, current);
229
0
        IMMER_RETHROW;
230
0
    }
231
21.6k
}
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
{
237
    return std::copy(first, last, out);
238
}
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
358k
{
243
358k
    using value_t = typename std::iterator_traits<SinkIter>::value_type;
244
358k
    auto current  = out;
245
358k
    IMMER_TRY {
246
1.14M
        for (; first != last; ++first, (void) ++current) {
247
789k
            ::new (const_cast<void*>(static_cast<const volatile void*>(
248
789k
                std::addressof(*current)))) value_t(*first);
249
789k
        }
250
358k
        return current;
251
358k
    }
252
358k
    IMMER_CATCH (...) {
253
0
        detail::destroy(out, current);
254
0
        IMMER_RETHROW;
255
0
    }
256
358k
}
257
258
template <typename Heap, typename T, typename... Args>
259
T* make(Args&&... args)
260
317k
{
261
317k
    auto ptr = Heap::allocate(sizeof(T));
262
317k
    IMMER_TRY {
263
317k
        return new (ptr) T(std::forward<Args>(args)...);
264
317k
    }
265
317k
    IMMER_CATCH (...) {
266
0
        Heap::deallocate(sizeof(T), ptr);
267
0
        IMMER_RETHROW;
268
0
    }
269
317k
}
immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::holder* immer::detail::make<immer::debug_size_heap<immer::cpp_heap>, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::holder, char const (&) [4]>(char const (&) [4])
Line
Count
Source
260
41.3k
{
261
41.3k
    auto ptr = Heap::allocate(sizeof(T));
262
41.3k
    IMMER_TRY {
263
41.3k
        return new (ptr) T(std::forward<Args>(args)...);
264
41.3k
    }
265
41.3k
    IMMER_CATCH (...) {
266
0
        Heap::deallocate(sizeof(T), ptr);
267
0
        IMMER_RETHROW;
268
0
    }
269
41.3k
}
immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::holder* immer::detail::make<immer::debug_size_heap<immer::cpp_heap>, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::holder, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Line
Count
Source
260
276k
{
261
276k
    auto ptr = Heap::allocate(sizeof(T));
262
276k
    IMMER_TRY {
263
276k
        return new (ptr) T(std::forward<Args>(args)...);
264
276k
    }
265
276k
    IMMER_CATCH (...) {
266
0
        Heap::deallocate(sizeof(T), ptr);
267
0
        IMMER_RETHROW;
268
0
    }
269
276k
}
immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::holder* immer::detail::make<immer::debug_size_heap<immer::cpp_heap>, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::holder>()
Line
Count
Source
260
1
{
261
1
    auto ptr = Heap::allocate(sizeof(T));
262
1
    IMMER_TRY {
263
1
        return new (ptr) T(std::forward<Args>(args)...);
264
1
    }
265
1
    IMMER_CATCH (...) {
266
0
        Heap::deallocate(sizeof(T), ptr);
267
0
        IMMER_RETHROW;
268
0
    }
269
1
}
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
{
310
    return x == 0 ? 0 : sizeof(std::size_t) * 8 - 1 - clz_(x);
311
}
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
{
324
    return pow == 0 ? 1 : num * ipow(num, pow - 1);
325
}
326
327
template <bool b, typename F>
328
auto static_if(F&& f) -> std::enable_if_t<b>
329
{
330
    std::forward<F>(f)(empty_t{});
331
}
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
{
345
    return std::forward<F2>(f2)(empty_t{});
346
}
347
348
template <typename T, T value>
349
struct constantly
350
{
351
    template <typename... Args>
352
    T operator()(Args&&...) const
353
494k
    {
354
494k
        return value;
355
494k
    }
immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > const* immer::detail::constantly<immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > const*, (immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > const*)0>::operator()<>() const
Line
Count
Source
353
1.84k
    {
354
1.84k
        return value;
355
1.84k
    }
unsigned long immer::detail::constantly<unsigned long, 1ul>::operator()<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >&>(std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::box<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > >&) const
Line
Count
Source
353
246k
    {
354
246k
        return value;
355
246k
    }
unsigned long immer::detail::constantly<unsigned long, 0ul>::operator()<>() const
Line
Count
Source
353
246k
    {
354
246k
        return value;
355
246k
    }
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