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