|
1 | 1 | #pragma once |
2 | 2 |
|
3 | 3 | #include <cctype> |
| 4 | +#include <cstddef> |
4 | 5 | #include <functional> |
| 6 | +#include <type_traits> |
5 | 7 |
|
6 | 8 | #include <tsl/ordered_map.h> |
7 | 9 | #include <tsl/ordered_set.h> |
|
14 | 16 | #include <foonathan/memory/default_allocator.hpp> |
15 | 17 | #include <foonathan/memory/std_allocator.hpp> |
16 | 18 |
|
| 19 | +//pre c++ 26 |
| 20 | +namespace std { |
| 21 | + template<typename T> |
| 22 | + struct equal_to<std::reference_wrapper<const T>> { |
| 23 | + [[nodiscard]] bool operator()( |
| 24 | + std::reference_wrapper<const T> const& lhs, |
| 25 | + std::reference_wrapper<const T> const& rhs |
| 26 | + ) const noexcept { |
| 27 | + return lhs.get() == rhs.get(); |
| 28 | + } |
| 29 | + }; |
| 30 | +} |
| 31 | + |
17 | 32 | namespace OpenVic { |
18 | 33 | struct ordered_container_string_hash { |
19 | 34 | using is_transparent = void; |
@@ -44,46 +59,69 @@ namespace OpenVic { |
44 | 59 | struct container_hash<char const*> : ordered_container_string_hash {}; |
45 | 60 | template<typename T> |
46 | 61 | struct container_hash<T*> : std::hash<T const*> {}; |
| 62 | + template<typename T> |
| 63 | + struct container_hash<std::reference_wrapper<T>> : std::hash<const T> {}; |
| 64 | + template<typename T> |
| 65 | + struct container_hash<std::reference_wrapper<const T>> : std::hash<const T> {}; |
| 66 | + |
| 67 | + // Default: Use transparent equality |
| 68 | + template<typename T> |
| 69 | + struct default_equal_to_selector { |
| 70 | + using type = std::equal_to<>; |
| 71 | + }; |
| 72 | + |
| 73 | + // Specialization for reference_wrapper |
| 74 | + template<typename T> |
| 75 | + struct default_equal_to_selector<std::reference_wrapper<T>> { |
| 76 | + using type = std::equal_to<std::reference_wrapper<const T>>; |
| 77 | + }; |
| 78 | + template<typename T> |
| 79 | + struct default_equal_to_selector<std::reference_wrapper<const T>> { |
| 80 | + using type = std::equal_to<std::reference_wrapper<const T>>; |
| 81 | + }; |
| 82 | + |
| 83 | + template<typename T> |
| 84 | + using default_equal_to = typename default_equal_to_selector<T>::type; |
47 | 85 |
|
48 | 86 | // Useful for contiguous memory |
49 | 87 | template< |
50 | | - class Key, class T, class Hash = container_hash<Key>, class KeyEqual = std::equal_to<>, |
| 88 | + class Key, class T, class Hash = container_hash<Key>, class KeyEqual = default_equal_to<Key>, |
51 | 89 | class RawAllocator = foonathan::memory::default_allocator, class IndexType = std::uint_least32_t, |
52 | 90 | class Allocator = foonathan::memory::std_allocator<std::pair<Key, T>, memory::tracker<RawAllocator>>> |
53 | 91 | using vector_ordered_map = |
54 | 92 | tsl::ordered_map<Key, T, Hash, KeyEqual, Allocator, std::vector<std::pair<Key, T>, Allocator>, IndexType>; |
55 | 93 |
|
56 | 94 | // Useful for stable memory addresses (so long as you don't remove or insert values) |
57 | 95 | template< |
58 | | - class Key, class T, class Hash = container_hash<Key>, class KeyEqual = std::equal_to<>, |
| 96 | + class Key, class T, class Hash = container_hash<Key>, class KeyEqual = default_equal_to<Key>, |
59 | 97 | class RawAllocator = foonathan::memory::default_allocator, class IndexType = std::uint_least32_t, |
60 | 98 | class Allocator = foonathan::memory::std_allocator<std::pair<Key, T>, memory::tracker<RawAllocator>>> |
61 | 99 | using deque_ordered_map = |
62 | 100 | tsl::ordered_map<Key, T, Hash, KeyEqual, Allocator, OpenVic::utility::deque<std::pair<Key, T>, Allocator>, IndexType>; |
63 | 101 |
|
64 | 102 | template< |
65 | | - class Key, class T, class Hash = container_hash<Key>, class KeyEqual = std::equal_to<>, |
| 103 | + class Key, class T, class Hash = container_hash<Key>, class KeyEqual = default_equal_to<Key>, |
66 | 104 | class RawAllocator = foonathan::memory::default_allocator, class IndexType = std::uint_least32_t, |
67 | 105 | class Allocator = foonathan::memory::std_allocator<std::pair<Key, T>, memory::tracker<RawAllocator>>> |
68 | 106 | using ordered_map = vector_ordered_map<Key, T, Hash, KeyEqual, RawAllocator, IndexType, Allocator>; |
69 | 107 |
|
70 | 108 | // Useful for contiguous memory |
71 | 109 | template< |
72 | | - class Key, class Hash = container_hash<Key>, class KeyEqual = std::equal_to<>, |
| 110 | + class Key, class Hash = container_hash<Key>, class KeyEqual = default_equal_to<Key>, |
73 | 111 | class RawAllocator = foonathan::memory::default_allocator, class IndexType = std::uint_least32_t, |
74 | 112 | class Allocator = foonathan::memory::std_allocator<Key, memory::tracker<RawAllocator>>> |
75 | 113 | using vector_ordered_set = tsl::ordered_set<Key, Hash, KeyEqual, Allocator, std::vector<Key, Allocator>, IndexType>; |
76 | 114 |
|
77 | 115 | // Useful for stable memory addresses (so long as you don't remove or insert values) |
78 | 116 | template< |
79 | | - class Key, class Hash = container_hash<Key>, class KeyEqual = std::equal_to<>, |
| 117 | + class Key, class Hash = container_hash<Key>, class KeyEqual = default_equal_to<Key>, |
80 | 118 | class RawAllocator = foonathan::memory::default_allocator, class IndexType = std::uint_least32_t, |
81 | 119 | class Allocator = foonathan::memory::std_allocator<Key, memory::tracker<RawAllocator>>> |
82 | 120 | using deque_ordered_set = |
83 | 121 | tsl::ordered_set<Key, Hash, KeyEqual, Allocator, OpenVic::utility::deque<Key, Allocator>, IndexType>; |
84 | 122 |
|
85 | 123 | template< |
86 | | - class Key, class Hash = container_hash<Key>, class KeyEqual = std::equal_to<>, |
| 124 | + class Key, class Hash = container_hash<Key>, class KeyEqual = default_equal_to<Key>, |
87 | 125 | class RawAllocator = foonathan::memory::default_allocator, class IndexType = std::uint_least32_t, |
88 | 126 | class Allocator = foonathan::memory::std_allocator<Key, memory::tracker<RawAllocator>>> |
89 | 127 | using ordered_set = vector_ordered_set<Key, Hash, KeyEqual, RawAllocator, IndexType, Allocator>; |
|
0 commit comments