diff --git a/include/tsl/robin_hash.h b/include/tsl/robin_hash.h index 5fdc07f..525ad34 100644 --- a/include/tsl/robin_hash.h +++ b/include/tsl/robin_hash.h @@ -356,7 +356,8 @@ class bucket_entry : public bucket_entry_hash<StoreHash> { * Behaviour is undefined if the destructor of `ValueType` throws. */ template <class ValueType, class KeySelect, class ValueSelect, class Hash, - class KeyEqual, class Allocator, bool StoreHash, class GrowthPolicy> + class KeyEqual, class Allocator, bool StoreHash, class GrowthPolicy, + class ValueTypeIt> class robin_hash : private Hash, private KeyEqual, private GrowthPolicy { private: template <typename U> @@ -387,6 +388,12 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy { using iterator = robin_iterator<false>; using const_iterator = robin_iterator<true>; + using value_type_it = ValueTypeIt; + using reference_it = value_type_it&; + using const_reference_it = const value_type_it&; + using pointer_it = value_type_it*; + using const_pointer_it = const value_type_it*; + private: /** * Either store the hash because we are asked by the `StoreHash` template @@ -463,10 +470,16 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy { public: using iterator_category = std::forward_iterator_tag; - using value_type = const typename robin_hash::value_type; + using value_type = typename robin_hash::value_type_it; using difference_type = std::ptrdiff_t; - using reference = value_type&; - using pointer = value_type*; + using reference = + typename std::conditional<IsConst, + typename robin_hash::const_reference_it, + typename robin_hash::reference_it>::type; + using pointer = + typename std::conditional<IsConst, + typename robin_hash::const_pointer_it, + typename robin_hash::pointer_it>::type; robin_iterator() noexcept {} @@ -499,9 +512,13 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy { return U()(m_bucket->value()); } - reference operator*() const { return m_bucket->value(); } + reference operator*() const { + return reinterpret_cast<reference>(m_bucket->value()); + } - pointer operator->() const { return std::addressof(m_bucket->value()); } + pointer operator->() const { + return reinterpret_cast<pointer>(std::addressof(m_bucket->value())); + } robin_iterator& operator++() { while (true) { diff --git a/include/tsl/robin_map.h b/include/tsl/robin_map.h index aeb354c..496a34d 100644 --- a/include/tsl/robin_map.h +++ b/include/tsl/robin_map.h @@ -105,6 +105,15 @@ class robin_map { key_type& operator()(std::pair<Key, T>& key_value) noexcept { return key_value.first; } + + const key_type& operator()( + const std::pair<const Key, T>& key_value) const noexcept { + return key_value.first; + } + + const key_type& operator()(std::pair<const Key, T>& key_value) noexcept { + return key_value.first; + } }; class ValueSelect { @@ -121,9 +130,10 @@ class robin_map { } }; - using ht = detail_robin_hash::robin_hash<std::pair<Key, T>, KeySelect, - ValueSelect, Hash, KeyEqual, - Allocator, StoreHash, GrowthPolicy>; + using ht = + detail_robin_hash::robin_hash<std::pair<Key, T>, KeySelect, ValueSelect, + Hash, KeyEqual, Allocator, StoreHash, + GrowthPolicy, std::pair<const Key, T>>; public: using key_type = typename ht::key_type; diff --git a/include/tsl/robin_set.h b/include/tsl/robin_set.h index 5478950..61099d9 100644 --- a/include/tsl/robin_set.h +++ b/include/tsl/robin_set.h @@ -101,8 +101,9 @@ class robin_set { key_type& operator()(Key& key) noexcept { return key; } }; - using ht = detail_robin_hash::robin_hash<Key, KeySelect, void, Hash, KeyEqual, - Allocator, StoreHash, GrowthPolicy>; + using ht = + detail_robin_hash::robin_hash<Key, KeySelect, void, Hash, KeyEqual, + Allocator, StoreHash, GrowthPolicy, Key>; public: using key_type = typename ht::key_type;