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