1 /* 2 Copyright (c) 2005-2021 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #ifndef __TBB_detail__hash_compare_H 18 #define __TBB_detail__hash_compare_H 19 20 #include <functional> 21 22 #include "_containers_helpers.h" 23 24 namespace tbb { 25 namespace detail { 26 namespace d1 { 27 28 template <typename Key, typename Hash, typename KeyEqual> 29 class hash_compare { 30 using is_transparent_hash = has_transparent_key_equal<Key, Hash, KeyEqual>; 31 public: 32 using hasher = Hash; 33 using key_equal = typename is_transparent_hash::type; 34 35 hash_compare() = default; hash_compare(hasher hash,key_equal equal)36 hash_compare( hasher hash, key_equal equal ) : my_hasher(hash), my_equal(equal) {} 37 operator()38 std::size_t operator()( const Key& key ) const { 39 return std::size_t(my_hasher(key)); 40 } 41 operator()42 bool operator()( const Key& key1, const Key& key2 ) const { 43 return my_equal(key1, key2); 44 } 45 46 template <typename K, typename = typename std::enable_if<is_transparent_hash::value, K>::type> operator()47 std::size_t operator()( const K& key ) const { 48 return std::size_t(my_hasher(key)); 49 } 50 51 template <typename K1, typename K2, typename = typename std::enable_if<is_transparent_hash::value, K1>::type> operator()52 bool operator()( const K1& key1, const K2& key2 ) const { 53 return my_equal(key1, key2); 54 } 55 hash_function()56 hasher hash_function() const { 57 return my_hasher; 58 } 59 key_eq()60 key_equal key_eq() const { 61 return my_equal; 62 } 63 64 65 private: 66 hasher my_hasher; 67 key_equal my_equal; 68 }; // class hash_compare 69 70 //! hash_compare that is default argument for concurrent_hash_map 71 template <typename Key> 72 class tbb_hash_compare { 73 public: hash(const Key & a)74 std::size_t hash( const Key& a ) const { return my_hash_func(a); } 75 #if defined(_MSC_VER) && _MSC_VER <= 1900 76 #pragma warning (push) 77 // MSVC 2015 throws a strange warning: 'std::size_t': forcing value to bool 'true' or 'false' 78 #pragma warning (disable: 4800) 79 #endif equal(const Key & a,const Key & b)80 bool equal( const Key& a, const Key& b ) const { return my_key_equal(a, b); } 81 #if defined(_MSC_VER) && _MSC_VER <= 1900 82 #pragma warning (pop) 83 #endif 84 private: 85 std::hash<Key> my_hash_func; 86 std::equal_to<Key> my_key_equal; 87 }; 88 89 } // namespace d1 90 #if __TBB_CPP20_CONCEPTS_PRESENT 91 inline namespace d0 { 92 93 template <typename HashCompare, typename Key> 94 concept hash_compare = std::copy_constructible<HashCompare> && requires(const std::remove_reference_t<HashCompare> & hc,const Key & key1,const Key & key2)95 requires( const std::remove_reference_t<HashCompare>& hc, const Key& key1, const Key& key2 ) { 96 { hc.hash(key1) } -> std::same_as<std::size_t>; 97 { hc.equal(key1, key2) } -> std::convertible_to<bool>; 98 }; 99 100 } // namespace d0 101 #endif // __TBB_CPP20_CONCEPTS_PRESENT 102 } // namespace detail 103 } // namespace tbb 104 105 #if TBB_DEFINE_STD_HASH_SPECIALIZATIONS 106 107 namespace std { 108 109 template <typename T, typename U> 110 struct hash<std::pair<T, U>> { 111 public: 112 std::size_t operator()( const std::pair<T, U>& p ) const { 113 return first_hash(p.first) ^ second_hash(p.second); 114 } 115 116 private: 117 std::hash<T> first_hash; 118 std::hash<U> second_hash; 119 }; // struct hash<std::pair> 120 121 // Apple clang and MSVC defines their own specializations for std::hash<std::basic_string<T, Traits, Alloc>> 122 #if !(_LIBCPP_VERSION) && !(_CPPLIB_VER) 123 124 template <typename CharT, typename Traits, typename Allocator> 125 struct hash<std::basic_string<CharT, Traits, Allocator>> { 126 public: 127 std::size_t operator()( const std::basic_string<CharT, Traits, Allocator>& s ) const { 128 std::size_t h = 0; 129 for ( const CharT* c = s.c_str(); *c; ++c ) { 130 h = h * hash_multiplier ^ char_hash(*c); 131 } 132 return h; 133 } 134 135 private: 136 static constexpr std::size_t hash_multiplier = tbb::detail::select_size_t_constant<2654435769U, 11400714819323198485ULL>::value; 137 138 std::hash<CharT> char_hash; 139 }; // struct hash<std::basic_string> 140 141 #endif // !(_LIBCPP_VERSION || _CPPLIB_VER) 142 143 } // namespace std 144 145 #endif // TBB_DEFINE_STD_HASH_SPECIALIZATIONS 146 147 #endif // __TBB_detail__hash_compare_H 148